diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml
index 02fe640f07..88b261970f 100644
--- a/.buildkite/pipeline.full.yml
+++ b/.buildkite/pipeline.full.yml
@@ -6,14 +6,16 @@ steps:
queue: macos-14
artifact_paths: build/fixture-minimal.apk
command: make fixture-minimal
+ env:
+ JAVA_VERSION: 17
- label: ':android: Build Example App'
timeout_in_minutes: 5
agents:
queue: macos-14
+ command: 'make example-app'
env:
JAVA_VERSION: 17
- command: 'make example-app'
- label: ':android: Build debug fixture APK'
key: "fixture-debug"
@@ -24,6 +26,8 @@ steps:
- "build/fixture-debug.apk"
- "build/fixture-debug/*"
command: make fixture-debug
+ env:
+ JAVA_VERSION: 17
- label: ':android: Build Scan'
timeout_in_minutes: 10
@@ -488,6 +492,72 @@ steps:
concurrency_group: 'bitbar'
concurrency_method: eager
+ - label: ':bitbar: Android 14 NDK r21 end-to-end tests - batch 1'
+ depends_on: "fixture-r21"
+ timeout_in_minutes: 60
+ plugins:
+ artifacts#v1.9.0:
+ download:
+ - "build/fixture-r21-url.txt"
+ - "build/fixture-r21/*"
+ upload:
+ - "maze_output/failed/**/*"
+ - "maze_output/metrics.csv"
+ docker-compose#v4.7.0:
+ pull: maze-runner
+ run: maze-runner
+ service-ports: true
+ command:
+ - "features/full_tests"
+ - "--exclude=features/full_tests/[^a-k].*.feature"
+ - "--app=@build/fixture-r21-url.txt"
+ - "--app-activity=com.bugsnag.android.mazerunner.MainActivity"
+ - "--app-package=com.bugsnag.android.mazerunner"
+ - "--appium-version=1.22"
+ - "--farm=bb"
+ - "--device=ANDROID_14"
+ - "--no-tunnel"
+ - "--aws-public-ip"
+ - "--fail-fast"
+ env:
+ TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21"
+ concurrency: 25
+ concurrency_group: 'bitbar'
+ concurrency_method: eager
+
+ - label: ':bitbar: Android 14 NDK r21 end-to-end tests - batch 2'
+ depends_on: "fixture-r21"
+ timeout_in_minutes: 60
+ plugins:
+ artifacts#v1.9.0:
+ download:
+ - "build/fixture-r21-url.txt"
+ - "build/fixture-r21/*"
+ upload:
+ - "maze_output/failed/**/*"
+ - "maze_output/metrics.csv"
+ docker-compose#v4.7.0:
+ pull: maze-runner
+ run: maze-runner
+ service-ports: true
+ command:
+ - "features/full_tests"
+ - "--exclude=features/full_tests/[^l-z].*.feature"
+ - "--app=@build/fixture-r21-url.txt"
+ - "--app-activity=com.bugsnag.android.mazerunner.MainActivity"
+ - "--app-package=com.bugsnag.android.mazerunner"
+ - "--appium-version=1.22"
+ - "--farm=bb"
+ - "--device=ANDROID_14"
+ - "--no-tunnel"
+ - "--aws-public-ip"
+ - "--fail-fast"
+ env:
+ TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21"
+ concurrency: 25
+ concurrency_group: 'bitbar'
+ concurrency_method: eager
+
# If there is a tag present activate a manual publishing step
- block: 'Trigger package publish'
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
index 1ed4bcd747..fc336dedd3 100644
--- a/.buildkite/pipeline.yml
+++ b/.buildkite/pipeline.yml
@@ -21,6 +21,8 @@ steps:
- bundle install
- make fixture-r19
- bundle exec upload-app --farm=bb --app=./build/fixture-r19.apk --app-id-file=build/fixture-r19-url.txt
+ env:
+ JAVA_VERSION: 17
- label: ':android: Build fixture APK r21'
key: "fixture-r21"
@@ -35,6 +37,8 @@ steps:
- bundle install
- make fixture-r21
- bundle exec upload-app --farm=bb --app=./build/fixture-r21.apk --app-id-file=build/fixture-r21-url.txt
+ env:
+ JAVA_VERSION: 17
- label: ':android: Coding standards checks'
timeout_in_minutes: 20
@@ -67,6 +71,8 @@ steps:
commands:
- cd features/fixtures/mazerunner
- ./gradlew ktlintCheck detekt checkstyle
+ env:
+ JAVA_VERSION: 17
- label: ':android: Android size reporting'
timeout_in_minutes: 10
@@ -80,6 +86,16 @@ steps:
queue: macos-14
command: './gradlew test'
+ - label: ':android: Instrumentation tests'
+ timeout_in_minutes: 10
+ plugins:
+ artifacts#v1.9.0:
+ upload: "bugsnag-*/build/reports/androidTests/connected/**/*.html"
+ agents:
+ queue: macos-14
+ command: './scripts/run-connected-checks.rb'
+ env:
+ API_LEVEL: 30
#
# BitBar steps
#
@@ -346,6 +362,38 @@ steps:
concurrency_group: 'bitbar'
concurrency_method: eager
+ - label: ':bitbar: Android 14 NDK r21 smoke tests'
+ depends_on: "fixture-r21"
+ timeout_in_minutes: 60
+ plugins:
+ artifacts#v1.9.0:
+ download:
+ - "build/fixture-r21-url.txt"
+ - "build/fixture-r21/*"
+ upload:
+ - "maze_output/failed/**/*"
+ - "maze_output/metrics.csv"
+ docker-compose#v4.7.0:
+ pull: maze-runner
+ run: maze-runner
+ service-ports: true
+ command:
+ - "features/smoke_tests"
+ - "--app=@build/fixture-r21-url.txt"
+ - "--app-activity=com.bugsnag.android.mazerunner.MainActivity"
+ - "--app-package=com.bugsnag.android.mazerunner"
+ - "--appium-version=1.22"
+ - "--farm=bb"
+ - "--device=ANDROID_14"
+ - "--no-tunnel"
+ - "--aws-public-ip"
+ - "--fail-fast"
+ env:
+ TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21"
+ concurrency: 25
+ concurrency_group: 'bitbar'
+ concurrency_method: eager
+
- label: 'Conditionally include device farms/full tests'
agents:
queue: macos-14
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e501cbd60..42901e967d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 6.6.0 (2024-06-19)
+
+### Enhancements
+
+* Support for Android Kernels with a 16kB page size
+ [#2040](https://github.com/bugsnag/bugsnag-android/pull/2040)
+
+### Bug fixes
+
+* Corrected the behavior when `Bugsnag.startSession` is called when `config.autoTrackSessions=true`, the first automatic session will now be correctly discarded
+ [#2033](https://github.com/bugsnag/bugsnag-android/pull/2033)
+* Avoid a possible crash in the ANR plugin when the native ANR library failed to load.
+ [#2039](https://github.com/bugsnag/bugsnag-android/pull/2039)
+
## 6.5.0 (2024-05-15)
### Enhancements
diff --git a/Makefile b/Makefile
index 0e5bba7b8f..2ee1038902 100644
--- a/Makefile
+++ b/Makefile
@@ -34,31 +34,31 @@ notifier:
fixture-r19: notifier
# Build the r19 test fixture
- @./gradlew -PTEST_FIXTURE_NDK_VERSION=19.2.5345600 \
+ @cd ./features/fixtures/mazerunner && ./gradlew -PTEST_FIXTURE_NDK_VERSION=19.2.5345600 \
-PTEST_FIXTURE_NAME=fixture-r19.apk \
- -p=features/fixtures/mazerunner assembleRelease -x check
+ assembleRelease -x check
@ruby scripts/copy-build-files.rb release r19
fixture-r21: notifier
# Build the r21 test fixture
- @./gradlew -PTEST_FIXTURE_NDK_VERSION=21.4.7075529 \
+ @cd ./features/fixtures/mazerunner && ./gradlew -PTEST_FIXTURE_NDK_VERSION=21.4.7075529 \
-PTEST_FIXTURE_NAME=fixture-r21.apk \
- -p=features/fixtures/mazerunner assembleRelease -x check
+ assembleRelease -x check
@ruby scripts/copy-build-files.rb release r21
fixture-minimal: notifier
# Build the minimal test fixture
- @./gradlew -PMINIMAL_FIXTURE=true \
+ @cd ./features/fixtures/mazerunner && ./gradlew -PMINIMAL_FIXTURE=true \
-PTEST_FIXTURE_NDK_VERSION=17.2.4988734 \
-PTEST_FIXTURE_NAME=fixture-minimal.apk \
- -p=features/fixtures/mazerunner assembleRelease -x check
+ assembleRelease -x check
@ruby scripts/copy-build-files.rb release minimal
fixture-debug: notifier
# Build the minimal test fixture
- @./gradlew -PTEST_FIXTURE_NDK_VERSION=17.2.4988734 \
+ @cd ./features/fixtures/mazerunner && ./gradlew -PTEST_FIXTURE_NDK_VERSION=17.2.4988734 \
-PTEST_FIXTURE_NAME=fixture-debug.apk \
- -p=features/fixtures/mazerunner assembleDebug -x check
+ assembleDebug -x check
@ruby scripts/copy-build-files.rb debug debug
example-app:
@@ -86,4 +86,4 @@ endif
check:
@./gradlew lint detekt ktlintCheck checkstyle
@./scripts/run-cpp-check.sh
- @./scripts/run-clang-format-ci-check.sh
+ @./scripts/run-clang-format-ci-check.sh
\ No newline at end of file
diff --git a/bugsnag-android-core/api/bugsnag-android-core.api b/bugsnag-android-core/api/bugsnag-android-core.api
index ecca487084..04f73e66b5 100644
--- a/bugsnag-android-core/api/bugsnag-android-core.api
+++ b/bugsnag-android-core/api/bugsnag-android-core.api
@@ -378,6 +378,7 @@ public class com/bugsnag/android/Event : com/bugsnag/android/FeatureFlagAware, c
public fun setContext (Ljava/lang/String;)V
public fun setGroupingHash (Ljava/lang/String;)V
public fun setSeverity (Lcom/bugsnag/android/Severity;)V
+ public fun setTraceCorrelation (Ljava/util/UUID;J)V
public fun setUnhandled (Z)V
public fun setUser (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
protected fun shouldDiscardClass ()Z
@@ -476,6 +477,7 @@ public class com/bugsnag/android/NativeInterface {
public static fun addMetadata (Ljava/lang/String;Ljava/util/Map;)V
public static fun clearMetadata (Ljava/lang/String;Ljava/lang/String;)V
public static fun createEvent (Ljava/lang/Throwable;Lcom/bugsnag/android/Client;Lcom/bugsnag/android/SeverityReason;)Lcom/bugsnag/android/Event;
+ public static fun deliverReport (Ljava/io/File;)V
public static fun deliverReport ([B[B[BLjava/lang/String;Z)V
public static fun getApp ()Ljava/util/Map;
public static fun getAppVersion ()Ljava/lang/String;
diff --git a/bugsnag-android-core/detekt-baseline.xml b/bugsnag-android-core/detekt-baseline.xml
index a5e99e257b..80214ff537 100644
--- a/bugsnag-android-core/detekt-baseline.xml
+++ b/bugsnag-android-core/detekt-baseline.xml
@@ -20,6 +20,9 @@
LongParameterList:NativeStackframe.kt$NativeStackframe$( /** * The name of the method that was being executed */ var method: String?, /** * The location of the source file */ var file: String?, /** * The line number within the source file this stackframe refers to */ var lineNumber: Number?, /** * The address of the instruction where the event occurred. */ var frameAddress: Long?, /** * The address of the function where the event occurred. */ var symbolAddress: Long?, /** * The address of the library where the event occurred. */ var loadAddress: Long?, /** * Whether this frame identifies the program counter */ var isPC: Boolean?, /** * The type of the error */ var type: ErrorType? = null, /** * Identifies the exact build this frame originates from. */ var codeIdentifier: String? = null, )
LongParameterList:StateEvent.kt$StateEvent.Install$( @JvmField val apiKey: String, @JvmField val autoDetectNdkCrashes: Boolean, @JvmField val appVersion: String?, @JvmField val buildUuid: String?, @JvmField val releaseStage: String?, @JvmField val lastRunInfoPath: String, @JvmField val consecutiveLaunchCrashes: Int, @JvmField val sendThreads: ThreadSendPolicy, @JvmField val maxBreadcrumbs: Int )
LongParameterList:ThreadState.kt$ThreadState$( allThreads: List<JavaThread>, currentThread: JavaThread, exc: Throwable?, isUnhandled: Boolean, maxThreadCount: Int, threadCollectionTimeLimitMillis: Long, projectPackages: Collection<String>, logger: Logger )
+ MagicNumber:BugsnagEventMapper.kt$BugsnagEventMapper$16
+ MagicNumber:BugsnagEventMapper.kt$BugsnagEventMapper$32
+ MagicNumber:BugsnagEventMapper.kt$BugsnagEventMapper$56
MagicNumber:DefaultDelivery.kt$DefaultDelivery$299
MagicNumber:DefaultDelivery.kt$DefaultDelivery$429
MagicNumber:DefaultDelivery.kt$DefaultDelivery$499
@@ -55,7 +58,6 @@
SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$exception: Exception
SwallowedException:DeviceIdFilePersistence.kt$DeviceIdFilePersistence$exc: OverlappingFileLockException
SwallowedException:EventStore.kt$EventStore$exception: RejectedExecutionException
- SwallowedException:EventStore.kt$EventStore$ioe: Exception
SwallowedException:ForegroundDetector.kt$ForegroundDetector$e: Exception
SwallowedException:ImmutableConfig.kt$e: Exception
SwallowedException:JsonHelperTest.kt$JsonHelperTest$e: IllegalArgumentException
diff --git a/bugsnag-android-core/src/main/CMakeLists.txt b/bugsnag-android-core/src/main/CMakeLists.txt
index c2cebef409..281c8ee11a 100644
--- a/bugsnag-android-core/src/main/CMakeLists.txt
+++ b/bugsnag-android-core/src/main/CMakeLists.txt
@@ -1,15 +1,19 @@
set(BUGSNAG_VERSION 1.0.1)
add_library( # Specifies the name of the library.
- bugsnag-root-detection
- # Sets the library as a shared library.
- SHARED
- # Provides a relative path to your source file(s).
- jni/root_detection.c
- )
+ bugsnag-root-detection
+ # Sets the library as a shared library.
+ SHARED
+ # Provides a relative path to your source file(s).
+ jni/root_detection.c
+)
include_directories(jni)
-set_target_properties(bugsnag-root-detection
- PROPERTIES
- COMPILE_OPTIONS
- -Werror -Wall -pedantic)
+set(EXTRA_LINK_FLAGS "-Wl,-z,max-page-size=16384")
+
+set_target_properties(
+ bugsnag-root-detection
+ PROPERTIES
+ COMPILE_OPTIONS -Werror -Wall -pedantic
+ LINK_FLAGS "${EXTRA_LINK_FLAGS}"
+)
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/BugsnagEventMapper.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/BugsnagEventMapper.kt
index c3af9864b5..e44902d423 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/BugsnagEventMapper.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/BugsnagEventMapper.kt
@@ -7,6 +7,7 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone
+import java.util.UUID
internal class BugsnagEventMapper(
private val logger: Logger
@@ -93,6 +94,16 @@ internal class BugsnagEventMapper(
// populate internalMetrics
event.internalMetrics = InternalMetricsImpl(map["usage"] as MutableMap?)
+ // populate correlation
+ (map["correlation"] as? Map)?.let {
+ val traceId = parseTraceId(it["traceId"])
+ val spanId = it["spanId"]?.parseUnsignedLong()
+
+ if (traceId != null && spanId != null) {
+ event.traceCorrelation = TraceCorrelation(traceId, spanId)
+ }
+ }
+
return event
}
@@ -234,16 +245,15 @@ internal class BugsnagEventMapper(
}
}
- // SimpleDateFormat isn't thread safe, cache one instance per thread as needed.
- private val ndkDateFormatHolder = object : ThreadLocal() {
- override fun initialValue(): DateFormat {
- return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
- timeZone = TimeZone.getTimeZone("UTC")
+ private fun String.toDate(): Date {
+ if (isNotEmpty() && this[0] == 't') {
+ // date is in the format 't{epoch millis}'
+ val timestamp = substring(1)
+ timestamp.toLongOrNull()?.let {
+ return Date(it)
}
}
- }
- private fun String.toDate(): Date {
return try {
DateUtils.fromIso8601(this)
} catch (pe: IllegalArgumentException) {
@@ -251,4 +261,31 @@ internal class BugsnagEventMapper(
?: throw IllegalArgumentException("cannot parse date $this")
}
}
+
+ private fun parseTraceId(traceId: String?): UUID? {
+ if (traceId?.length != 32) return null
+ val mostSigBits = traceId.substring(0, 16).parseUnsignedLong() ?: return null
+ val leastSigBits = traceId.substring(16).parseUnsignedLong() ?: return null
+
+ return UUID(mostSigBits, leastSigBits)
+ }
+
+ private fun String.parseUnsignedLong(): Long? {
+ if (length != 16) return null
+ return try {
+ (substring(0, 2).toLong(16) shl 56) or
+ substring(2).toLong(16)
+ } catch (nfe: NumberFormatException) {
+ null
+ }
+ }
+
+ // SimpleDateFormat isn't thread safe, cache one instance per thread as needed.
+ private val ndkDateFormatHolder = object : ThreadLocal() {
+ override fun initialValue(): DateFormat {
+ return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
+ timeZone = TimeZone.getTimeZone("UTC")
+ }
+ }
+ }
}
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java b/bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java
index ac498bb174..4dc9b31e4f 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java
@@ -10,6 +10,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.regex.Pattern;
/**
@@ -382,6 +383,21 @@ public void setUnhandled(boolean unhandled) {
impl.setUnhandled(unhandled);
}
+ /**
+ * Associate this event with a specific trace. This is usually done automatically when
+ * using bugsnag-android-performance, but can also be set manually if required.
+ *
+ * @param traceId the ID of the trace the event occurred within
+ * @param spanId the ID of the span that the event occurred within
+ */
+ public void setTraceCorrelation(@NonNull UUID traceId, long spanId) {
+ if (traceId != null) {
+ impl.setTraceCorrelation(new TraceCorrelation(traceId, spanId));
+ } else {
+ logNull("traceId");
+ }
+ }
+
protected boolean shouldDiscardClass() {
return impl.shouldDiscardClass();
}
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventInternal.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventInternal.kt
index 4a1881f71d..88b46df334 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventInternal.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventInternal.kt
@@ -119,6 +119,8 @@ internal class EventInternal : FeatureFlagAware, JsonStream.Streamable, Metadata
*/
internal var userImpl: User
+ var traceCorrelation: TraceCorrelation? = null
+
fun getUnhandledOverridden(): Boolean = severityReason.unhandledOverridden
fun getOriginalUnhandled(): Boolean = severityReason.originalUnhandled
@@ -193,6 +195,10 @@ internal class EventInternal : FeatureFlagAware, JsonStream.Streamable, Metadata
writer.name("featureFlags").value(featureFlags)
+ traceCorrelation?.let { correlation ->
+ writer.name("correlation").value(correlation)
+ }
+
if (session != null) {
val copy = Session.copySession(session)
writer.name("session").beginObject()
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt
index 6eb471d22d..e6d8401ae9 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt
@@ -196,6 +196,7 @@ internal class EventStore(
return null
}
} catch (ioe: Exception) {
+ logger.w("could not parse event payload", ioe)
eventSource.clear()
}
val processedEvent = eventSource.event
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/FileStore.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/FileStore.kt
index 1e0ba13731..235ba699bf 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/FileStore.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/FileStore.kt
@@ -14,7 +14,7 @@ import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
internal abstract class FileStore(
- private val storageDir: File,
+ val storageDir: File,
private val maxStoreCount: Int,
private val comparator: Comparator,
protected open val logger: Logger,
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/NativeInterface.java b/bugsnag-android-core/src/main/java/com/bugsnag/android/NativeInterface.java
index 6f622fdf27..de0da4a21c 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/NativeInterface.java
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/NativeInterface.java
@@ -21,6 +21,7 @@
import java.util.Map;
import java.util.regex.Pattern;
+
/**
* Used as the entry point for native code to allow proguard to obfuscate other areas if needed
*/
@@ -430,6 +431,25 @@ public static void deliverReport(@Nullable byte[] releaseStageBytes,
}
}
+ /**
+ * Attempt to deliver an existing event file that is not current enqueued for delivery. The
+ * filename is expected to be in the standard {@link EventFilenameInfo} format, and the file
+ * should contain a correctly formatted {@link Event} object. This method will attempt to
+ * move the file into place, and flush the queue asynchronously. If the file cannot be moved
+ * into the queue directory, the file is deleted before returning.
+ *
+ * @param reportFile the file to enqueue for delivery
+ */
+ public static void deliverReport(@NonNull File reportFile) {
+ EventStore eventStore = getClient().eventStore;
+ File eventFile = new File(eventStore.getStorageDir(), reportFile.getName());
+ if (reportFile.renameTo(eventFile)) {
+ eventStore.flushAsync();
+ } else {
+ reportFile.delete();
+ }
+ }
+
/**
* Notifies using the Android SDK
*
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt
index 4cc446d679..f89f73b880 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/Notifier.kt
@@ -7,7 +7,7 @@ import java.io.IOException
*/
class Notifier @JvmOverloads constructor(
var name: String = "Android Bugsnag Notifier",
- var version: String = "6.5.0",
+ var version: String = "6.6.0",
var url: String = "https://bugsnag.com"
) : JsonStream.Streamable {
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/SessionTracker.java b/bugsnag-android-core/src/main/java/com/bugsnag/android/SessionTracker.java
index 9fc2747f5b..25fb7058c4 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/SessionTracker.java
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/SessionTracker.java
@@ -36,7 +36,7 @@ class SessionTracker extends BaseObservable implements ForegroundDetector.OnActi
private volatile Session currentSession = null;
final BackgroundTaskService backgroundTaskService;
final Logger logger;
- private boolean shouldSuppressFirstAutoSession = false;
+ private boolean shouldSuppressFirstAutoSession = true;
SessionTracker(ImmutableConfig configuration,
CallbackState callbackState,
@@ -108,9 +108,13 @@ private boolean shouldDiscardSession(boolean autoCaptured) {
&& existingSession != null
&& !existingSession.isAutoCaptured()
&& shouldSuppressFirstAutoSession) {
- shouldSuppressFirstAutoSession = true;
+ shouldSuppressFirstAutoSession = false;
return true;
}
+
+ if (autoCaptured) {
+ shouldSuppressFirstAutoSession = false;
+ }
}
return false;
}
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/TraceCorrelation.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/TraceCorrelation.kt
new file mode 100644
index 0000000000..4fc01ac60f
--- /dev/null
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/TraceCorrelation.kt
@@ -0,0 +1,20 @@
+package com.bugsnag.android
+
+import java.util.UUID
+
+internal data class TraceCorrelation(val traceId: UUID, val spanId: Long) : JsonStream.Streamable {
+ override fun toStream(writer: JsonStream) {
+ writer.beginObject()
+ .name("traceId").value(traceId.toHexString())
+ .name("spanId").value(spanId.toHexString())
+ writer.endObject()
+ }
+
+ private fun UUID.toHexString(): String {
+ return "%016x%016x".format(mostSignificantBits, leastSignificantBits)
+ }
+
+ private fun Long.toHexString(): String {
+ return "%016x".format(this)
+ }
+}
diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/InternalMetricsImpl.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/InternalMetricsImpl.kt
index 6e648e5f48..0900b9166c 100644
--- a/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/InternalMetricsImpl.kt
+++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/InternalMetricsImpl.kt
@@ -53,7 +53,7 @@ class InternalMetricsImpl(source: Map? = null) : InternalMetrics {
// This is currently the only place where we set static data.
// When that changes in future, we'll need a StaticData object to properly merge data
// coming from multiple sources.
- NdkPluginCaller.setStaticData(mapOf("usage" to mapOf("config" to configDifferences)))
+ NdkPluginCaller.setStaticData(mapOf("config" to configDifferences))
}
override fun setCallbackCounts(newCallbackCounts: Map) {
diff --git a/bugsnag-android-core/src/test/java/com/bugsnag/android/EventSerializationTest.kt b/bugsnag-android-core/src/test/java/com/bugsnag/android/EventSerializationTest.kt
index f930fe313c..84175e34e7 100644
--- a/bugsnag-android-core/src/test/java/com/bugsnag/android/EventSerializationTest.kt
+++ b/bugsnag-android-core/src/test/java/com/bugsnag/android/EventSerializationTest.kt
@@ -9,6 +9,7 @@ import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameter
import org.junit.runners.Parameterized.Parameters
import java.util.Date
+import java.util.UUID
@RunWith(Parameterized::class)
internal class EventSerializationTest {
@@ -35,7 +36,8 @@ internal class EventSerializationTest {
createEvent {
val user = User("123", "foo@example.com", "Joe")
val apiKey = "BUGSNAG_API_KEY"
- it.session = Session("123", Date(0), user, false, Notifier(), NoopLogger, apiKey)
+ it.session =
+ Session("123", Date(0), user, false, Notifier(), NoopLogger, apiKey)
},
// threads included
@@ -82,6 +84,14 @@ internal class EventSerializationTest {
createEvent {
it.addFeatureFlag("no_variant")
it.addFeatureFlag("flag", "with_variant")
+ },
+
+ // with a trace correlation
+ createEvent {
+ it.setTraceCorrelation(
+ UUID(0x24b8b82900d34da3, -0x659434b74a5b9edc),
+ 0x3dbe7c7ae84945b9
+ )
}
)
}
diff --git a/bugsnag-android-core/src/test/resources/event_serialization_8.json b/bugsnag-android-core/src/test/resources/event_serialization_8.json
new file mode 100644
index 0000000000..982656fdb9
--- /dev/null
+++ b/bugsnag-android-core/src/test/resources/event_serialization_8.json
@@ -0,0 +1,41 @@
+{
+ "metaData": {},
+ "severity": "warning",
+ "severityReason": {
+ "type": "handledException",
+ "unhandledOverridden": false
+ },
+ "unhandled": false,
+ "exceptions": [],
+ "projectPackages":[
+ "com.example.foo"
+ ],
+ "user": {},
+ "app": {
+ "type": "android",
+ "versionCode": 0
+ },
+ "device": {
+ "cpuAbi": [],
+ "manufacturer": "samsung",
+ "model": "s7",
+ "osName": "android",
+ "osVersion": "7.1",
+ "runtimeVersions": {
+ "osBuild": "bulldog",
+ "androidApiLevel": "24"
+ },
+ "totalMemory": 109230923452,
+ "freeDisk": 22234423124,
+ "freeMemory": 92340255592,
+ "orientation": "portrait",
+ "time": "1970-01-01T00:00:00.000Z"
+ },
+ "breadcrumbs": [],
+ "threads": [],
+ "featureFlags": [],
+ "correlation": {
+ "traceId": "24b8b82900d34da39a6bcb48b5a46124",
+ "spanId": "3dbe7c7ae84945b9"
+ }
+}
diff --git a/bugsnag-plugin-android-anr/src/main/CMakeLists.txt b/bugsnag-plugin-android-anr/src/main/CMakeLists.txt
index f4bc87c22e..3777341157 100644
--- a/bugsnag-plugin-android-anr/src/main/CMakeLists.txt
+++ b/bugsnag-plugin-android-anr/src/main/CMakeLists.txt
@@ -1,23 +1,27 @@
set(BUGSNAG_VERSION 1.0.1)
add_library( # Specifies the name of the library.
- bugsnag-plugin-android-anr
- # Sets the library as a shared library.
- SHARED
- # Provides a relative path to your source file(s).
- jni/anr_google.c
- jni/anr_handler.c
- jni/bugsnag_anr.c
- jni/utils/string.c
- )
+ bugsnag-plugin-android-anr
+ # Sets the library as a shared library.
+ SHARED
+ # Provides a relative path to your source file(s).
+ jni/anr_google.c
+ jni/anr_handler.c
+ jni/bugsnag_anr.c
+ jni/utils/string.c
+)
include_directories(jni)
+set(EXTRA_LINK_FLAGS "-Wl,-z,max-page-size=16384")
+
target_link_libraries( # Specifies the target library.
- bugsnag-plugin-android-anr
- # Links the log library to the target library.
- log)
+ bugsnag-plugin-android-anr
+ # Links the log library to the target library.
+ log)
-set_target_properties(bugsnag-plugin-android-anr
- PROPERTIES
- COMPILE_OPTIONS
- -Werror -Wall -pedantic)
+set_target_properties(
+ bugsnag-plugin-android-anr
+ PROPERTIES
+ COMPILE_OPTIONS -Werror -Wall -pedantic
+ LINK_FLAGS "${EXTRA_LINK_FLAGS}"
+)
diff --git a/bugsnag-plugin-android-anr/src/main/java/com/bugsnag/android/AnrPlugin.kt b/bugsnag-plugin-android-anr/src/main/java/com/bugsnag/android/AnrPlugin.kt
index f2bcb924c2..5745b3e2fe 100644
--- a/bugsnag-plugin-android-anr/src/main/java/com/bugsnag/android/AnrPlugin.kt
+++ b/bugsnag-plugin-android-anr/src/main/java/com/bugsnag/android/AnrPlugin.kt
@@ -67,22 +67,25 @@ internal class AnrPlugin : Plugin {
}
private fun performOneTimeSetup(client: Client) {
- libraryLoader.loadLibrary("bugsnag-plugin-android-anr", client) {
+ val isLoaded = libraryLoader.loadLibrary("bugsnag-plugin-android-anr", client) {
val error = it.errors[0]
error.errorClass = "AnrLinkError"
error.errorMessage = LOAD_ERR_MSG
true
}
- @Suppress("UNCHECKED_CAST")
- val clz = loadClass("com.bugsnag.android.NdkPlugin") as Class?
- if (clz != null) {
- val ndkPlugin = client.getPlugin(clz)
- if (ndkPlugin != null) {
- val method = ndkPlugin.javaClass.getMethod("getSignalUnwindStackFunction")
-
- @Suppress("UNCHECKED_CAST")
- val function = method.invoke(ndkPlugin) as Long
- setUnwindFunction(function)
+
+ if (isLoaded) {
+ @Suppress("UNCHECKED_CAST")
+ val clz = loadClass("com.bugsnag.android.NdkPlugin") as Class?
+ if (clz != null) {
+ val ndkPlugin = client.getPlugin(clz)
+ if (ndkPlugin != null) {
+ val method = ndkPlugin.javaClass.getMethod("getSignalUnwindStackFunction")
+
+ @Suppress("UNCHECKED_CAST")
+ val function = method.invoke(ndkPlugin) as Long
+ setUnwindFunction(function)
+ }
}
}
}
diff --git a/bugsnag-plugin-android-ndk/api/bugsnag-plugin-android-ndk.api b/bugsnag-plugin-android-ndk/api/bugsnag-plugin-android-ndk.api
index cdc5a7496c..4b7eea278f 100644
--- a/bugsnag-plugin-android-ndk/api/bugsnag-plugin-android-ndk.api
+++ b/bugsnag-plugin-android-ndk/api/bugsnag-plugin-android-ndk.api
@@ -16,12 +16,11 @@ public final class com/bugsnag/android/ndk/NativeBridge : com/bugsnag/android/in
public final fun clearFeatureFlag (Ljava/lang/String;)V
public final fun clearFeatureFlags ()V
public final fun clearMetadataTab (Ljava/lang/String;)V
- public final fun deliverReportAtPath (Ljava/lang/String;)V
public final fun getCurrentCallbackSetCounts ()Ljava/util/Map;
public final fun getCurrentNativeApiCallUsage ()Ljava/util/Map;
public final fun getSignalUnwindStackFunction ()J
public final fun initCallbackCounts (Ljava/util/Map;)V
- public final fun install (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZIZII)V
+ public final fun install (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZIZII)V
public final fun notifyAddCallback (Ljava/lang/String;)V
public final fun notifyRemoveCallback (Ljava/lang/String;)V
public fun onStateChange (Lcom/bugsnag/android/StateEvent;)V
diff --git a/bugsnag-plugin-android-ndk/detekt-baseline.xml b/bugsnag-plugin-android-ndk/detekt-baseline.xml
index 57df3f72f2..af4ed869eb 100644
--- a/bugsnag-plugin-android-ndk/detekt-baseline.xml
+++ b/bugsnag-plugin-android-ndk/detekt-baseline.xml
@@ -3,9 +3,8 @@
CyclomaticComplexMethod:NativeBridge.kt$NativeBridge$override fun onStateChange(event: StateEvent)
- LongMethod:EventOnDiskTests.kt$EventOnDiskTests$@Test fun testEvent()
- LongParameterList:NativeBridge.kt$NativeBridge$( apiKey: String, reportingDirectory: String, lastRunInfoPath: String, consecutiveLaunchCrashes: Int, autoDetectNdkCrashes: Boolean, apiLevel: Int, is32bit: Boolean, threadSendPolicy: Int, maxBreadcrumbs: Int, )
- NestedBlockDepth:NativeBridge.kt$NativeBridge$private fun deliverPendingReports()
+ LongParameterList:NativeBridge.kt$NativeBridge$( apiKey: String, reportingDirectory: String, lastRunInfoPath: String, eventUUID: String, consecutiveLaunchCrashes: Int, autoDetectNdkCrashes: Boolean, apiLevel: Int, is32bit: Boolean, threadSendPolicy: Int, maxBreadcrumbs: Int, )
+ SwallowedException:ReportDiscardScanner.kt$ReportDiscardScanner$ex: Exception
TooManyFunctions:NativeBridge.kt$NativeBridge : StateObserver
UseCheckOrError:ResourceUtils.kt$throw IllegalStateException("Failed to read JSON from $resourceName")
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppMetadataSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppMetadataSerializationTest.kt
deleted file mode 100644
index 2d050023b9..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppMetadataSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class AppMetadataSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("app_meta_data_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppSerializationTest.kt
deleted file mode 100644
index bb67499cd2..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/AppSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class AppSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("app_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/BreadcrumbStateSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/BreadcrumbStateSerializationTest.kt
deleted file mode 100644
index aa9de489ea..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/BreadcrumbStateSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class BreadcrumbStateSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testBreadcrumbSerialization() {
- val expected = loadJson("breadcrumbs_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ContextSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ContextSerializationTest.kt
deleted file mode 100644
index 969f25e7b6..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ContextSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class ContextSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("context_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/CustomMetadataSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/CustomMetadataSerializationTest.kt
deleted file mode 100644
index 0d2c5d95f5..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/CustomMetadataSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class CustomMetadataSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("custom_meta_data_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/DeviceSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/DeviceSerializationTest.kt
deleted file mode 100644
index 2953883f00..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/DeviceSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class DeviceSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("device_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ExceptionSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ExceptionSerializationTest.kt
deleted file mode 100644
index c187ac0f34..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ExceptionSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class ExceptionSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("exception_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeJsonSerializeTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeJsonSerializeTest.kt
index 652db32832..f866a97837 100644
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeJsonSerializeTest.kt
+++ b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeJsonSerializeTest.kt
@@ -1,6 +1,10 @@
package com.bugsnag.android.ndk
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
import org.junit.Test
+import java.io.File
class NativeJsonSerializeTest {
@@ -11,10 +15,25 @@ class NativeJsonSerializeTest {
}
}
- external fun run(): Int
+ private val path = File(System.getProperty("java.io.tmpdir"), this::class.simpleName!!)
+
+ @Before
+ fun setupTmpdir() {
+ path.mkdirs()
+ }
+
+ @After
+ fun deleteTmpdir() {
+ path.deleteRecursively()
+ }
+
+ external fun run(outputDir: String): Int
@Test
fun testPassesNativeSuite() {
- verifyNativeRun(run())
+ verifyNativeRun(run(path.absolutePath))
+ val jsonFile = path.listFiles()!!.maxByOrNull { it.lastModified() }!!
+ val expected = loadJson("event_serialization.json")
+ assertEquals(expected, jsonFile.readText())
}
}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeStructToFileTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeStructToFileTest.kt
deleted file mode 100644
index d2fe5fdfa7..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeStructToFileTest.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Test
-
-class NativeStructToFileTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): Int
-
- @Test
- fun testPassesNativeSuite() {
- verifyNativeRun(run())
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ReportDiscardScannerTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ReportDiscardScannerTest.kt
new file mode 100644
index 0000000000..889cc207c6
--- /dev/null
+++ b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ReportDiscardScannerTest.kt
@@ -0,0 +1,38 @@
+package com.bugsnag.android.ndk
+
+import com.bugsnag.android.Client
+import com.bugsnag.android.Logger
+import com.bugsnag.android.NativeInterface
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnitRunner
+import java.io.File
+
+@RunWith(MockitoJUnitRunner::class)
+class ReportDiscardScannerTest {
+ @Mock
+ lateinit var client: Client
+
+ @Before
+ fun setupNativeInterface() {
+ NativeInterface.setClient(client)
+ }
+
+ @Test
+ fun discardStaticData() {
+ val discardScanner = ReportDiscardScanner(object : Logger {}, emptySet())
+ assertTrue(discardScanner.shouldDiscard(File("/data/data/something/there_is_some.static_data.json")))
+ }
+
+ @Test
+ fun discardNonJson() {
+ val discardScanner = ReportDiscardScanner(object : Logger {}, emptySet())
+ assertTrue(discardScanner.shouldDiscard(File("/data/data/683c6b92-b325-4987-80ad-77086509ca1e.dump")))
+ assertTrue(discardScanner.shouldDiscard(File("/data/data/683c6b92-b325-4987-80ad-77086509ca1e.binary")))
+ assertTrue(discardScanner.shouldDiscard(File("/data/data/something_not_quite.static_data.binary")))
+ assertTrue(discardScanner.shouldDiscard(File("/data/data/data.binary")))
+ }
+}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SessionSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SessionSerializationTest.kt
deleted file mode 100644
index d21934e9d9..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SessionSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class SessionSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("session_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SeverityReasonSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SeverityReasonSerializationTest.kt
deleted file mode 100644
index 4fedf3c166..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/SeverityReasonSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class SeverityReasonSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("severity_reason_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/StackframeSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/StackframeSerializationTest.kt
deleted file mode 100644
index 783942452a..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/StackframeSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class StackframeSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("stackframe_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ThreadSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ThreadSerializationTest.kt
deleted file mode 100644
index ca690e464d..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ThreadSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert
-import org.junit.Test
-
-class ThreadSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("thread_serialization.json")
- val json = run()
- Assert.assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/UserSerializationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/UserSerializationTest.kt
deleted file mode 100644
index 844e6873b7..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/UserSerializationTest.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.bugsnag.android.ndk
-
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-internal class UserSerializationTest {
-
- companion object {
- init {
- System.loadLibrary("bugsnag-ndk")
- System.loadLibrary("bugsnag-ndk-test")
- }
- }
-
- external fun run(): String
-
- @Test
- fun testPassesNativeSuite() {
- val expected = loadJson("user_serialization.json")
- val json = run()
- assertEquals(expected, json)
- }
-}
diff --git a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/migrations/EventMigrationTest.kt b/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/migrations/EventMigrationTest.kt
deleted file mode 100644
index 006e5dfab9..0000000000
--- a/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/migrations/EventMigrationTest.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.bugsnag.android.ndk.migrations
-
-import android.content.Context
-import androidx.test.platform.app.InstrumentationRegistry
-import com.bugsnag.android.repackaged.dslplatform.json.DslJson
-import org.junit.Before
-import java.io.File
-
-open class EventMigrationTest {
-
- private lateinit var context: Context
- private val json = DslJson