diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/RumDataWriter.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/RumDataWriter.kt index 77992b49a5..585fb19030 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/RumDataWriter.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/RumDataWriter.kt @@ -42,9 +42,7 @@ internal class RumDataWriter( is ActionEvent -> notifyEventSent(event.view.id, EventType.ACTION) is ResourceEvent -> notifyEventSent(event.view.id, EventType.RESOURCE) is ErrorEvent -> { - if (event.error.isCrash == true) { - notifyEventSent(event.view.id, EventType.CRASH) - } else { + if (event.error.isCrash != true) { notifyEventSent(event.view.id, EventType.ERROR) } } diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapper.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapper.kt index 7edabbbd6a..4f6557ec8e 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapper.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapper.kt @@ -42,7 +42,13 @@ internal data class RumEventMapper( return when (val bundledEvent = event.event) { is ViewEvent -> viewEventMapper.map(bundledEvent) is ActionEvent -> actionEventMapper.map(bundledEvent) - is ErrorEvent -> errorEventMapper.map(bundledEvent) + is ErrorEvent -> { + if (bundledEvent.error.isCrash != true) { + errorEventMapper.map(bundledEvent) + } else { + bundledEvent + } + } is ResourceEvent -> resourceEventMapper.map(bundledEvent) is LongTaskEvent -> longTaskEventMapper.map(bundledEvent) else -> { diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumRawEvent.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumRawEvent.kt index 05d6c33ef6..8aa82492ef 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumRawEvent.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumRawEvent.kt @@ -113,7 +113,6 @@ internal sealed class RumRawEvent { internal data class ErrorSent( val viewId: String, - val isCrash: Boolean, override val eventTime: Time = Time() ) : RumRawEvent() diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt index 57773d33c8..3a816762df 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt @@ -298,7 +298,13 @@ internal open class RumViewScope( userExtraAttributes = user.additionalProperties ) writer.write(rumEvent) - pendingErrorCount++ + if (event.isFatal) { + errorCount++ + crashCount++ + sendViewUpdate(event, writer) + } else { + pendingErrorCount++ + } } private fun onAddCustomTiming( @@ -383,7 +389,6 @@ internal open class RumViewScope( if (event.viewId == viewId) { pendingErrorCount-- errorCount++ - if (event.isCrash) crashCount++ sendViewUpdate(event, writer) } } diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitor.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitor.kt index a00ae88c5f..ab84715017 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitor.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitor.kt @@ -255,8 +255,7 @@ internal class DatadogRumMonitor( when (type) { EventType.ACTION -> handleEvent(RumRawEvent.ActionSent(viewId)) EventType.RESOURCE -> handleEvent(RumRawEvent.ResourceSent(viewId)) - EventType.ERROR -> handleEvent(RumRawEvent.ErrorSent(viewId, false)) - EventType.CRASH -> handleEvent(RumRawEvent.ErrorSent(viewId, true)) + EventType.ERROR -> handleEvent(RumRawEvent.ErrorSent(viewId)) EventType.LONG_TASK -> handleEvent(RumRawEvent.LongTaskSent(viewId)) EventType.VIEW -> { // Nothing to do @@ -268,7 +267,7 @@ internal class DatadogRumMonitor( when (type) { EventType.ACTION -> handleEvent(RumRawEvent.ActionDropped(viewId)) EventType.RESOURCE -> handleEvent(RumRawEvent.ResourceDropped(viewId)) - EventType.ERROR, EventType.CRASH -> handleEvent(RumRawEvent.ErrorDropped(viewId)) + EventType.ERROR -> handleEvent(RumRawEvent.ErrorDropped(viewId)) EventType.LONG_TASK -> handleEvent(RumRawEvent.LongTaskDropped(viewId)) EventType.VIEW -> { // Nothing to do @@ -293,14 +292,18 @@ internal class DatadogRumMonitor( } internal fun handleEvent(event: RumRawEvent) { - handler.removeCallbacks(keepAliveRunnable) - // avoid trowing a RejectedExecutionException - if (!executorService.isShutdown) { - executorService.submit { - synchronized(rootScope) { - rootScope.handleEvent(event, writer) + if (event is RumRawEvent.AddError && event.isFatal) { + rootScope.handleEvent(event, writer) + } else { + handler.removeCallbacks(keepAliveRunnable) + // avoid trowing a RejectedExecutionException + if (!executorService.isShutdown) { + executorService.submit { + synchronized(rootScope) { + rootScope.handleEvent(event, writer) + } + handler.postDelayed(keepAliveRunnable, KEEP_ALIVE_MS) } - handler.postDelayed(keepAliveRunnable, KEEP_ALIVE_MS) } } } diff --git a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/EventType.kt b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/EventType.kt index 3ce4190da3..f8fb007db1 100644 --- a/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/EventType.kt +++ b/dd-sdk-android/src/main/kotlin/com/datadog/android/rum/internal/monitor/EventType.kt @@ -11,6 +11,5 @@ internal enum class EventType { ACTION, RESOURCE, ERROR, - CRASH, LONG_TASK } diff --git a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/RumDataWriterTest.kt b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/RumDataWriterTest.kt index a6645a3088..1e965f4295 100644 --- a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/RumDataWriterTest.kt +++ b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/RumDataWriterTest.kt @@ -22,6 +22,9 @@ import com.datadog.android.utils.forge.Configurator import com.datadog.tools.unit.annotations.TestConfigurationsProvider import com.datadog.tools.unit.extensions.TestConfigurationExtension import com.datadog.tools.unit.extensions.config.TestConfiguration +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.eq +import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyZeroInteractions import fr.xgouchet.elmyr.annotation.Forgery @@ -210,7 +213,7 @@ internal class RumDataWriterTest { } @Test - fun `𝕄 notify the RumMonitor 𝕎 onDataWritten() { ErrorEvent isCrash=true }`( + fun `𝕄 not notify the RumMonitor 𝕎 onDataWritten() { ErrorEvent isCrash=true }`( @Forgery fakeModel: RumEvent, @Forgery errorEvent: ErrorEvent ) { @@ -225,7 +228,7 @@ internal class RumDataWriterTest { testedWriter.onDataWritten(rumEvent, fakeSerializedData) // Then - verify(rumMonitor.mockInstance).eventSent(errorEvent.view.id, EventType.CRASH) + verify(rumMonitor.mockInstance, never()).eventSent(eq(errorEvent.view.id), any()) verifyZeroInteractions(mockFileHandler) } diff --git a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapperTest.kt b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapperTest.kt index b5ad954ee2..2fc4606b4f 100644 --- a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapperTest.kt +++ b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/event/RumEventMapperTest.kt @@ -248,7 +248,10 @@ internal class RumEventMapperTest { @Test fun `M return null event W map returns null object { ErrorEvent }`(forge: Forge) { // GIVEN - val fakeBundledEvent = forge.getForgery() + val fakeErrorEvent = forge.getForgery() + val fakeBundledEvent = fakeErrorEvent.copy( + error = fakeErrorEvent.error.copy(isCrash = false) + ) fakeRumEvent = fakeRumEvent.copy(event = fakeBundledEvent) whenever(mockErrorEventMapper.map(fakeBundledEvent)) .thenReturn(null) @@ -265,6 +268,26 @@ internal class RumEventMapperTest { ) } + @Test + fun `M return event W map returns null object { fatal ErrorEvent }`(forge: Forge) { + // GIVEN + val fakeErrorEvent = forge.getForgery() + val fakeBundledEvent = fakeErrorEvent.copy( + error = fakeErrorEvent.error.copy(isCrash = true) + ) + fakeRumEvent = fakeRumEvent.copy(event = fakeBundledEvent) + whenever(mockErrorEventMapper.map(fakeBundledEvent)) + .thenReturn(null) + + // WHEN + val mappedRumEvent = testedRumEventMapper.map(fakeRumEvent) + + // THEN + assertThat(mappedRumEvent) + .isSameAs(fakeRumEvent) + .isEqualTo(fakeRumEvent) + } + @Test fun `M return null event W map returns null object { ActionEvent }`(forge: Forge) { // GIVEN diff --git a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeTest.kt b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeTest.kt index 0786af3ffa..a2b9e8b803 100644 --- a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeTest.kt +++ b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeTest.kt @@ -862,7 +862,7 @@ internal class RumViewScopeTest { @LongForgery(1) pending: Long ) { // Given - fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId, isCrash = false) + fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId) testedScope.pendingErrorCount = pending // When @@ -901,60 +901,15 @@ internal class RumViewScopeTest { assertThat(testedScope.pendingErrorCount).isEqualTo(pending - 1) } - @Test - fun `𝕄 send event 𝕎 handleEvent(ErrorSent) on active view {isCrash = true}`( - @LongForgery(1) pending: Long - ) { - // Given - fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId, isCrash = true) - testedScope.pendingErrorCount = pending - - // When - val result = testedScope.handleEvent(fakeEvent, mockWriter) - - // Then - argumentCaptor { - verify(mockWriter).write(capture()) - assertThat(lastValue) - .hasAttributes(fakeAttributes) - .hasUserExtraAttributes(fakeUserInfo.additionalProperties) - .hasViewData { - hasTimestamp(fakeEventTime.timestamp) - hasName(fakeName) - hasUrl(fakeUrl) - hasDurationGreaterThan(1) - hasVersion(2) - hasErrorCount(1) - hasCrashCount(1) - hasResourceCount(0) - hasActionCount(0) - hasLongTaskCount(0) - hasCpuMetric(null) - hasMemoryMetric(null, null) - hasRefreshRateMetric(null, null) - isActive(true) - hasNoCustomTimings() - hasUserInfo(fakeUserInfo) - hasViewId(testedScope.viewId) - hasApplicationId(fakeParentContext.applicationId) - hasSessionId(fakeParentContext.sessionId) - } - } - verifyNoMoreInteractions(mockWriter) - assertThat(result).isSameAs(testedScope) - assertThat(testedScope.pendingErrorCount).isEqualTo(pending - 1) - } - @Test fun `𝕄 do nothing 𝕎 handleEvent(ErrorSent) on active view {unknown viewId}`( @Forgery viewUuid: UUID, - @BoolForgery isCrash: Boolean, @LongForgery(1) pending: Long ) { // Given val viewId = viewUuid.toString() assumeTrue(viewId != testedScope.viewId) - fakeEvent = RumRawEvent.ErrorSent(viewId, isCrash) + fakeEvent = RumRawEvent.ErrorSent(viewId) testedScope.pendingErrorCount = pending // When @@ -1203,7 +1158,7 @@ internal class RumViewScopeTest { // Given testedScope.stopped = true testedScope.pendingErrorCount = 1 - fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId, isCrash = false) + fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId) // When val result = testedScope.handleEvent(fakeEvent, mockWriter) @@ -1241,53 +1196,9 @@ internal class RumViewScopeTest { assertThat(testedScope.pendingErrorCount).isEqualTo(0) } - @Test - fun `𝕄 send event 𝕎 handleEvent(ErrorSent) on stopped view {isCrash = true}`() { - // Given - testedScope.stopped = true - testedScope.pendingErrorCount = 1 - fakeEvent = RumRawEvent.ErrorSent(testedScope.viewId, isCrash = true) - - // When - val result = testedScope.handleEvent(fakeEvent, mockWriter) - - // Then - argumentCaptor { - verify(mockWriter).write(capture()) - assertThat(lastValue) - .hasAttributes(fakeAttributes) - .hasUserExtraAttributes(fakeUserInfo.additionalProperties) - .hasViewData { - hasTimestamp(fakeEventTime.timestamp) - hasName(fakeName) - hasUrl(fakeUrl) - hasDurationGreaterThan(1) - hasVersion(2) - hasErrorCount(1) - hasCrashCount(1) - hasResourceCount(0) - hasActionCount(0) - hasLongTaskCount(0) - hasCpuMetric(null) - hasMemoryMetric(null, null) - hasRefreshRateMetric(null, null) - isActive(false) - hasNoCustomTimings() - hasUserInfo(fakeUserInfo) - hasViewId(testedScope.viewId) - hasApplicationId(fakeParentContext.applicationId) - hasSessionId(fakeParentContext.sessionId) - } - } - verifyNoMoreInteractions(mockWriter) - assertThat(result).isNull() - assertThat(testedScope.pendingErrorCount).isEqualTo(0) - } - @Test fun `𝕄 do nothing 𝕎 handleEvent(ErrorSent) on stopped view {unknown viewId}`( @Forgery viewUuid: UUID, - @BoolForgery isCrash: Boolean, @LongForgery(1) pending: Long ) { // Given @@ -1295,7 +1206,7 @@ internal class RumViewScopeTest { testedScope.pendingErrorCount = pending val viewId = viewUuid.toString() assumeTrue(viewId != testedScope.viewId) - fakeEvent = RumRawEvent.ErrorSent(viewId, isCrash) + fakeEvent = RumRawEvent.ErrorSent(viewId) // When val result = testedScope.handleEvent(fakeEvent, mockWriter) @@ -2366,16 +2277,15 @@ internal class RumViewScopeTest { } @Test - fun `𝕄 send event 𝕎 handleEvent(AddError) {throwable=null, stacktrace=null}`( + fun `𝕄 send event 𝕎 handleEvent(AddError) {throwable=null, stacktrace=null, fatal=false}`( @StringForgery message: String, @Forgery source: RumErrorSource, - @BoolForgery fatal: Boolean, forge: Forge ) { // Given testedScope.activeActionScope = mockActionScope val attributes = forge.exhaustiveAttributes(excludedKeys = fakeAttributes.keys) - fakeEvent = RumRawEvent.AddError(message, source, null, null, fatal, attributes) + fakeEvent = RumRawEvent.AddError(message, source, null, null, false, attributes) // When val result = testedScope.handleEvent(fakeEvent, mockWriter) @@ -2392,7 +2302,47 @@ internal class RumViewScopeTest { hasMessage(message) hasSource(source) hasStackTrace(null) - isCrash(fatal) + isCrash(false) + hasUserInfo(fakeUserInfo) + hasConnectivityInfo(fakeNetworkInfo) + hasView(testedScope.viewId, testedScope.name, testedScope.url) + hasApplicationId(fakeParentContext.applicationId) + hasSessionId(fakeParentContext.sessionId) + hasActionId(fakeActionId) + hasErrorType(null) + } + } + verifyNoMoreInteractions(mockWriter) + assertThat(result).isSameAs(testedScope) + } + + @Test + fun `𝕄 send event 𝕎 handleEvent(AddError) {throwable=null, stacktrace=null, fatal=true}`( + @StringForgery message: String, + @Forgery source: RumErrorSource, + forge: Forge + ) { + // Given + testedScope.activeActionScope = mockActionScope + val attributes = forge.exhaustiveAttributes(excludedKeys = fakeAttributes.keys) + fakeEvent = RumRawEvent.AddError(message, source, null, null, true, attributes) + + // When + val result = testedScope.handleEvent(fakeEvent, mockWriter) + + // Then + argumentCaptor { + verify(mockWriter, times(2)).write(capture()) + + assertThat(firstValue) + .hasAttributes(attributes) + .hasUserExtraAttributes(fakeUserInfo.additionalProperties) + .hasErrorData { + hasTimestamp(fakeEvent.eventTime.timestamp) + hasMessage(message) + hasSource(source) + hasStackTrace(null) + isCrash(true) hasUserInfo(fakeUserInfo) hasConnectivityInfo(fakeNetworkInfo) hasView(testedScope.viewId, testedScope.name, testedScope.url) @@ -2401,6 +2351,33 @@ internal class RumViewScopeTest { hasActionId(fakeActionId) hasErrorType(null) } + + assertThat(lastValue) + .hasAttributes(fakeAttributes) + .hasUserExtraAttributes(fakeUserInfo.additionalProperties) + .hasViewData { + hasTimestamp(fakeEventTime.timestamp) + hasName(fakeName) + hasUrl(fakeUrl) + hasDurationGreaterThan(1) + hasLoadingTime(null) + hasLoadingType(null) + hasVersion(2) + hasErrorCount(1) + hasCrashCount(1) + hasResourceCount(0) + hasActionCount(0) + hasLongTaskCount(0) + hasCpuMetric(null) + hasMemoryMetric(null, null) + hasRefreshRateMetric(null, null) + isActive(true) + hasNoCustomTimings() + hasUserInfo(fakeUserInfo) + hasViewId(testedScope.viewId) + hasApplicationId(fakeParentContext.applicationId) + hasSessionId(fakeParentContext.sessionId) + } } verifyNoMoreInteractions(mockWriter) assertThat(result).isSameAs(testedScope) @@ -2479,7 +2456,7 @@ internal class RumViewScopeTest { // Then argumentCaptor { - verify(mockWriter).write(capture()) + verify(mockWriter, times(2)).write(capture()) assertThat(firstValue) .hasAttributes(attributes) @@ -2498,6 +2475,33 @@ internal class RumViewScopeTest { hasActionId(fakeActionId) hasErrorType(throwable.javaClass.canonicalName) } + + assertThat(lastValue) + .hasAttributes(fakeAttributes) + .hasUserExtraAttributes(fakeUserInfo.additionalProperties) + .hasViewData { + hasTimestamp(fakeEventTime.timestamp) + hasName(fakeName) + hasUrl(fakeUrl) + hasDurationGreaterThan(1) + hasLoadingTime(null) + hasLoadingType(null) + hasVersion(2) + hasErrorCount(1) + hasCrashCount(1) + hasResourceCount(0) + hasActionCount(0) + hasLongTaskCount(0) + hasCpuMetric(null) + hasMemoryMetric(null, null) + hasRefreshRateMetric(null, null) + isActive(true) + hasNoCustomTimings() + hasUserInfo(fakeUserInfo) + hasViewId(testedScope.viewId) + hasApplicationId(fakeParentContext.applicationId) + hasSessionId(fakeParentContext.sessionId) + } } verifyNoMoreInteractions(mockWriter) assertThat(result).isSameAs(testedScope) @@ -2519,7 +2523,7 @@ internal class RumViewScopeTest { source, throwable, null, - true, + false, attributes, type = errorType ) @@ -2539,7 +2543,7 @@ internal class RumViewScopeTest { hasMessage(message) hasSource(source) hasStackTrace(throwable.loggableStackTrace()) - isCrash(true) + isCrash(false) hasUserInfo(fakeUserInfo) hasConnectivityInfo(fakeNetworkInfo) hasView(testedScope.viewId, testedScope.name, testedScope.url) @@ -2578,7 +2582,7 @@ internal class RumViewScopeTest { // Then argumentCaptor { - verify(mockWriter).write(capture()) + verify(mockWriter, times(2)).write(capture()) assertThat(firstValue) .hasAttributes(attributes) @@ -2597,6 +2601,33 @@ internal class RumViewScopeTest { hasActionId(fakeActionId) hasErrorType(throwable.javaClass.canonicalName) } + + assertThat(lastValue) + .hasAttributes(fakeAttributes) + .hasUserExtraAttributes(fakeUserInfo.additionalProperties) + .hasViewData { + hasTimestamp(fakeEventTime.timestamp) + hasName(fakeName) + hasUrl(fakeUrl) + hasDurationGreaterThan(1) + hasLoadingTime(null) + hasLoadingType(null) + hasVersion(2) + hasErrorCount(1) + hasCrashCount(1) + hasResourceCount(0) + hasActionCount(0) + hasLongTaskCount(0) + hasCpuMetric(null) + hasMemoryMetric(null, null) + hasRefreshRateMetric(null, null) + isActive(true) + hasNoCustomTimings() + hasUserInfo(fakeUserInfo) + hasViewId(testedScope.viewId) + hasApplicationId(fakeParentContext.applicationId) + hasSessionId(fakeParentContext.sessionId) + } } verifyNoMoreInteractions(mockWriter) assertThat(result).isSameAs(testedScope) @@ -2647,15 +2678,14 @@ internal class RumViewScopeTest { } @Test - fun `𝕄 wait for pending Error 𝕎 handleEvent(AddError) on active view`( + fun `𝕄 wait for pending Error 𝕎 handleEvent(AddError) on active view {fatal=false}`( @StringForgery message: String, @Forgery source: RumErrorSource, - @StringForgery stacktrace: String, - @BoolForgery fatal: Boolean + @StringForgery stacktrace: String ) { // Given testedScope.pendingErrorCount = 0 - fakeEvent = RumRawEvent.AddError(message, source, null, stacktrace, fatal, emptyMap()) + fakeEvent = RumRawEvent.AddError(message, source, null, stacktrace, false, emptyMap()) val result = testedScope.handleEvent(fakeEvent, mockWriter) @@ -2663,6 +2693,22 @@ internal class RumViewScopeTest { assertThat(result).isSameAs(testedScope) } + @Test + fun `𝕄 not wait for pending Error 𝕎 handleEvent(AddError) on active view {fatal=true}`( + @StringForgery message: String, + @Forgery source: RumErrorSource, + @StringForgery stacktrace: String + ) { + // Given + testedScope.pendingErrorCount = 0 + fakeEvent = RumRawEvent.AddError(message, source, null, stacktrace, true, emptyMap()) + + val result = testedScope.handleEvent(fakeEvent, mockWriter) + + assertThat(testedScope.pendingErrorCount).isEqualTo(0) + assertThat(result).isSameAs(testedScope) + } + @Test fun `𝕄 decrease pending Error 𝕎 handleEvent(ErrorDropped) on active view`( @LongForgery(1) pending: Long diff --git a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitorTest.kt b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitorTest.kt index 7ac2f4a446..f136863465 100644 --- a/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitorTest.kt +++ b/dd-sdk-android/src/test/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitorTest.kt @@ -497,14 +497,19 @@ internal class DatadogRumMonitorTest { } @Test - fun `M delegate event to rootScope W addCrash()`( + fun `M delegate event to rootScope on current thread W addCrash()`( @StringForgery message: String, @Forgery source: RumErrorSource, @Forgery throwable: Throwable ) { + // Given + testedMonitor.drainExecutorService() + + // When testedMonitor.addCrash(message, source, throwable) Thread.sleep(PROCESSING_DELAY) + // Then argumentCaptor { verify(mockScope).handleEvent(capture(), same(mockWriter))