Skip to content

Commit fedfbf6

Browse files
committed
test(event) error options end to end tests
1 parent f1c4417 commit fedfbf6

File tree

14 files changed

+155
-43
lines changed

14 files changed

+155
-43
lines changed

bugsnag-android-core/detekt-baseline.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<ID>LongParameterList:DeviceWithState.kt$DeviceWithState$( buildInfo: DeviceBuildInfo, jailbroken: Boolean?, id: String?, locale: String?, totalMemory: Long?, runtimeVersions: MutableMap&lt;String, Any>, /** * The number of free bytes of storage available on the device */ var freeDisk: Long?, /** * The number of free bytes of memory available on the device */ var freeMemory: Long?, /** * The orientation of the device when the event occurred: either portrait or landscape */ var orientation: String?, /** * The timestamp on the device when the event occurred */ var time: Date? )</ID>
2323
<ID>LongParameterList:EventFilenameInfo.kt$EventFilenameInfo.Companion$( obj: Any, uuid: String = UUID.randomUUID().toString(), apiKey: String?, timestamp: Long = System.currentTimeMillis(), config: ImmutableConfig, isLaunching: Boolean? = null )</ID>
2424
<ID>LongParameterList:EventInternal.kt$EventInternal$( apiKey: String, logger: Logger, breadcrumbs: MutableList&lt;Breadcrumb> = mutableListOf(), discardClasses: Set&lt;Pattern> = setOf(), errors: MutableList&lt;Error> = mutableListOf(), metadata: Metadata = Metadata(), featureFlags: FeatureFlags = FeatureFlags(), originalError: Throwable? = null, projectPackages: Collection&lt;String> = setOf(), severityReason: SeverityReason = SeverityReason.newInstance(SeverityReason.REASON_HANDLED_EXCEPTION), threads: MutableList&lt;Thread> = mutableListOf(), user: User = User(), redactionKeys: Set&lt;Pattern>? = null, isAttemptDeliveryOnCrash: Boolean = false )</ID>
25-
<ID>LongParameterList:EventInternal.kt$EventInternal$( originalError: Throwable? = null, config: ImmutableConfig, severityReason: SeverityReason, data: Metadata = Metadata(), featureFlags: FeatureFlags = FeatureFlags(), captureStacktrace: Boolean = true, captureThreads: Boolean = true, excludeStacktrace: Boolean? = null )</ID>
25+
<ID>LongParameterList:EventInternal.kt$EventInternal$( originalError: Throwable? = null, config: ImmutableConfig, severityReason: SeverityReason, data: Metadata = Metadata(), featureFlags: FeatureFlags = FeatureFlags(), captureStacktrace: Boolean = true, captureThreads: Boolean = true, )</ID>
2626
<ID>LongParameterList:EventStorageModule.kt$EventStorageModule$( contextModule: ContextModule, configModule: ConfigModule, dataCollectionModule: DataCollectionModule, bgTaskService: BackgroundTaskService, trackerModule: TrackerModule, systemServiceModule: SystemServiceModule, notifier: Notifier, callbackState: CallbackState )</ID>
2727
<ID>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, )</ID>
2828
<ID>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 )</ID>

bugsnag-android-core/src/main/java/com/bugsnag/android/Bugsnag.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,9 @@ public static void notify(@NonNull final Throwable exception,
259259
* Notify Bugsnag of a handled exception
260260
*
261261
* @param exception the exception to send to Bugsnag
262+
* @param options additional options to adjust the reporting of the exception
262263
* @param onError callback invoked on the generated error report for
263264
* additional modification
264-
* @param options the error options
265265
*/
266266
public static void notify(@NonNull final Throwable exception,
267267
@Nullable final ErrorOptions options,

bugsnag-android-core/src/main/java/com/bugsnag/android/Client.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ public void notify(
767767
SeverityReason severityReason = SeverityReason.newInstance(REASON_HANDLED_EXCEPTION);
768768
Event event = createEventWithOptions(exc, severityReason, options);
769769
event.setGroupingDiscriminator(getGroupingDiscriminator());
770-
populateAndNotifyAndroidEvent(event, onError);
770+
populateAndNotifyAndroidEvent(event,options, onError);
771771
} else {
772772
logNull("notify");
773773
}
@@ -789,20 +789,15 @@ private Event createEventWithOptions(
789789
);
790790
}
791791

792-
793792
final CaptureOptions capture = options != null ? options.getCapture() : null;
794793
final Metadata metadata = capture == null || capture.getMetadata() == null
795794
? metadataState.getMetadata()
796795
: captureSelectedMetadata(capture.getMetadata());
797-
final FeatureFlags featureFlags = capture == null || capture.getMetadata() == null
796+
final FeatureFlags featureFlags = capture == null || capture.getFeatureFlags()
798797
? featureFlagState.getFeatureFlags()
799798
: new FeatureFlags();
800-
final Boolean Stacktrace = capture == null || capture.getMetadata() == null
801-
? null
802-
: capture.getStacktrace();
803-
final Boolean Threads = capture == null || capture.getMetadata() == null
804-
? null
805-
: capture.getThreads();
799+
final boolean stacktrace = capture == null || capture.getStacktrace();
800+
final boolean threads = capture == null || capture.getThreads();
806801

807802
Event event;
808803
if (options != null || capture != null) {
@@ -812,7 +807,8 @@ private Event createEventWithOptions(
812807
severityReason,
813808
metadata,
814809
featureFlags,
815-
true,
810+
stacktrace,
811+
threads,
816812
logger
817813
);
818814
} else {
@@ -822,16 +818,16 @@ private Event createEventWithOptions(
822818
severityReason,
823819
metadataState.getMetadata(),
824820
featureFlagState.getFeatureFlags(),
825-
Stacktrace,
826-
Threads,
821+
stacktrace,
822+
threads,
827823
logger);
828824
}
829825
return event;
830826
}
831827

832828
private Metadata captureSelectedMetadata(@Nullable Set<String> metadata) {
833829
Map<String, Map<String, Object>> all = snapshotAllMetadataTabsExcludingAppDevice();
834-
Metadata selectedMetadataTabs = null;
830+
Metadata selectedMetadataTabs = new Metadata();
835831
if (metadata != null || !metadata.isEmpty()) {
836832
for (Map.Entry<String, Map<String, Object>> e : all.entrySet()) {
837833
if (metadata.contains(e.getKey())) {

bugsnag-android-core/src/main/java/com/bugsnag/android/ErrorOptions.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class CaptureOptions(
2121
/**
2222
* Controls which custom metadata tabs are included.
2323
* - null: all metadata tabs captured
24-
* - empty set: only app and device tabs captured
24+
* - empty set: no custom metadata captured
2525
* - set of names: app, device, and specified tabs captured
2626
*
2727
* Note: app and device tabs are always captured.
@@ -61,22 +61,22 @@ class CaptureOptions(
6161
@JvmStatic
6262
@JvmOverloads
6363
fun captureOnly(fields: Int, metadata: Set<String>? = null): CaptureOptions {
64-
return captureNothing().apply {
65-
stacktrace = (fields and CAPTURE_STACKTRACE) != 0
66-
breadcrumbs = (fields and CAPTURE_BREADCRUMBS) != 0
67-
featureFlags = (fields and CAPTURE_FEATURE_FLAGS) != 0
68-
threads = (fields and CAPTURE_THREADS) != 0
69-
user = (fields and CAPTURE_USER) != 0
70-
this.metadata = metadata
71-
}
64+
return CaptureOptions(
65+
stacktrace = (fields and CAPTURE_STACKTRACE) != 0,
66+
breadcrumbs = (fields and CAPTURE_BREADCRUMBS) != 0,
67+
featureFlags = (fields and CAPTURE_FEATURE_FLAGS) != 0,
68+
threads = (fields and CAPTURE_THREADS) != 0,
69+
user = (fields and CAPTURE_USER) != 0,
70+
metadata = metadata
71+
)
7272
}
7373

7474
/**
7575
* Return CaptureOptions that will not capture any optional fields.
7676
*/
7777
@JvmStatic
7878
fun captureNothing(): CaptureOptions {
79-
return captureOnly(0)
79+
return captureOnly(0, emptySet())
8080
}
8181
}
8282
}

bugsnag-android-core/src/main/java/com/bugsnag/android/Event.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,6 @@ public class Event implements JsonStream.Streamable, MetadataAware, UserAware, F
4343
logger);
4444
}
4545

46-
Event(@Nullable Throwable originalError,
47-
@NonNull ImmutableConfig config,
48-
@NonNull SeverityReason severityReason,
49-
@NonNull Metadata metadata,
50-
@NonNull FeatureFlags featureFlags,
51-
@Nullable Boolean excludeStacktrace,
52-
@NonNull Logger logger) {
53-
this(new EventInternal(originalError, config, severityReason, metadata, featureFlags,
54-
excludeStacktrace),
55-
logger);
56-
}
57-
5846
Event(@Nullable Throwable originalError,
5947
@NonNull ImmutableConfig config,
6048
@NonNull SeverityReason severityReason,

bugsnag-android-core/src/main/java/com/bugsnag/android/EventInternal.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal class EventInternal : FeatureFlagAware, JsonStream.Streamable, Metadata
2020
featureFlags: FeatureFlags = FeatureFlags(),
2121
captureStacktrace: Boolean = true,
2222
captureThreads: Boolean = true,
23-
excludeStacktrace: Boolean? = null
2423
) : this(
2524
config.apiKey,
2625
config.logger,
@@ -29,7 +28,7 @@ internal class EventInternal : FeatureFlagAware, JsonStream.Streamable, Metadata
2928
when {
3029
originalError == null -> mutableListOf()
3130
!captureStacktrace -> {
32-
val error = Error.createError(originalError, config.projectPackages, config.logger, excludeStacktrace)[0]
31+
val error = Error.createError(originalError, config.projectPackages, config.logger, !captureStacktrace)[0]
3332
mutableListOf(error)
3433
}
3534
else -> Error.createError(originalError, config.projectPackages, config.logger, false)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.bugsnag.android
2+
3+
import org.junit.Assert.assertEquals
4+
import org.junit.Assert.assertFalse
5+
import org.junit.Assert.assertNull
6+
import org.junit.Assert.assertTrue
7+
import org.junit.Test
8+
9+
class CaptureOptionsTest {
10+
11+
@Test
12+
fun testDefaultValues() {
13+
val options = CaptureOptions()
14+
assertTrue(options.breadcrumbs)
15+
assertTrue(options.featureFlags)
16+
assertNull(options.metadata)
17+
assertTrue(options.stacktrace)
18+
assertTrue(options.threads)
19+
assertTrue(options.user)
20+
}
21+
22+
@Test
23+
fun testCaptureOnlyStacktraceAndUser() {
24+
val fields = CaptureOptions.CAPTURE_STACKTRACE or CaptureOptions.CAPTURE_USER
25+
val options = CaptureOptions.captureOnly(fields)
26+
assertTrue(options.stacktrace)
27+
assertFalse(options.breadcrumbs)
28+
assertFalse(options.featureFlags)
29+
assertFalse(options.threads)
30+
assertTrue(options.user)
31+
assertNull(options.metadata)
32+
}
33+
34+
@Test
35+
fun testCaptureOnlyWithMetadata() {
36+
val fields = CaptureOptions.CAPTURE_BREADCRUMBS or CaptureOptions.CAPTURE_FEATURE_FLAGS
37+
val metadataTabs = setOf("customTab")
38+
val options = CaptureOptions.captureOnly(fields, metadataTabs)
39+
assertFalse(options.stacktrace)
40+
assertTrue(options.breadcrumbs)
41+
assertTrue(options.featureFlags)
42+
assertFalse(options.threads)
43+
assertFalse(options.user)
44+
assertEquals(metadataTabs, options.metadata)
45+
}
46+
47+
@Test
48+
fun testCaptureNothing() {
49+
val options = CaptureOptions.captureNothing()
50+
assertFalse(options.stacktrace)
51+
assertFalse(options.breadcrumbs)
52+
assertFalse(options.featureFlags)
53+
assertFalse(options.threads)
54+
assertFalse(options.user)
55+
assertEquals(emptySet<String>(), options.metadata)
56+
}
57+
}

examples/sdk-app-example/app/src/main/java/com/example/bugsnag/android/BaseCrashyActivity.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import androidx.activity.enableEdgeToEdge
99
import androidx.appcompat.app.AppCompatActivity
1010
import com.bugsnag.android.BreadcrumbType
1111
import com.bugsnag.android.Bugsnag
12+
import com.bugsnag.android.CaptureOptions
1213
import com.bugsnag.android.Configuration
14+
import com.bugsnag.android.ErrorOptions
1315
import com.bugsnag.android.Severity
1416
import com.example.foo.CrashyClass
1517
import com.google.android.material.snackbar.Snackbar
@@ -93,7 +95,14 @@ open class BaseCrashyActivity : AppCompatActivity() {
9395
try {
9496
throw RuntimeException("Non-Fatal Crash")
9597
} catch (e: RuntimeException) {
96-
Bugsnag.notify(e) {
98+
99+
100+
val errorOptions: ErrorOptions = ErrorOptions(CaptureOptions.captureNothing())
101+
Bugsnag.addMetadata("custom", "key", "value")
102+
Bugsnag.leaveBreadcrumb("Test breadcrumb")
103+
Bugsnag.addFeatureFlag("testFeatureFlag", "variantA")
104+
Bugsnag.setUser("123", "[email protected]", "Jane Doe")
105+
Bugsnag.notify(e, errorOptions){
97106
showSnackbar()
98107
true
99108
}

examples/sdk-app-example/app/src/main/java/com/example/bugsnag/android/ExampleApplication.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class ExampleApplication : Application() {
3636
config.setUser("123456", "[email protected]", "Joe Bloggs")
3737
config.addMetadata("user", "age", 31)
3838
config.addPlugin(bugsnagOkHttpPlugin)
39-
config.isAttemptDeliveryOnCrash = true
4039

4140
// Configure the persistence directory when running MultiProcessActivity in a separate
4241
// process to ensure the two Bugsnag clients are independent
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.bugsnag.android.mazerunner.scenarios
2+
3+
import android.content.Context
4+
import com.bugsnag.android.Bugsnag
5+
import com.bugsnag.android.CaptureOptions
6+
import com.bugsnag.android.Configuration
7+
import com.bugsnag.android.ErrorOptions
8+
9+
class ErrorOptionsScenario(
10+
config: Configuration,
11+
context: Context,
12+
eventMetadata: String?
13+
) : Scenario(config, context, eventMetadata) {
14+
private val errorOptions = ErrorOptions(CaptureOptions.captureNothing())
15+
16+
override fun startScenario() {
17+
super.startScenario()
18+
Bugsnag.addMetadata("custom", "key", "value")
19+
Bugsnag.leaveBreadcrumb("Test breadcrumb")
20+
Bugsnag.addFeatureFlag("testFeatureFlag", "variantA")
21+
Bugsnag.setUser("123", "[email protected]", "Jane Doe")
22+
Bugsnag.notify(generateException(), errorOptions, null)
23+
}
24+
}

0 commit comments

Comments
 (0)