Skip to content

Commit f0b7f1a

Browse files
Merge branch 'main' into remove-unused-proj-properties
2 parents fc2d679 + ea995b9 commit f0b7f1a

File tree

24 files changed

+343
-236
lines changed

24 files changed

+343
-236
lines changed

embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/injection/DataSourceModuleImplTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal class DataSourceModuleImplTest {
1616
fakeInitModule,
1717
FakeWorkerThreadModule(
1818
fakeInitModule = fakeInitModule,
19-
testWorkerName = Worker.Background.NonIoRegWorker
19+
testWorker = Worker.Background.NonIoRegWorker
2020
),
2121
)
2222
assertSame(module.dataCaptureOrchestrator, module.embraceFeatureRegistry)

embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/session/SessionOrchestrationModuleImplTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ internal class SessionOrchestrationModuleImplTest {
2525
private val configService = FakeConfigService()
2626
private val workerThreadModule = FakeWorkerThreadModule(
2727
fakeInitModule = initModule,
28-
testWorkerName = Worker.Background.NonIoRegWorker
28+
testWorker = Worker.Background.NonIoRegWorker
2929
)
3030

3131
@Test

embrace-android-features/src/test/java/io/embrace/android/embracesdk/internal/crash/LastRunCrashVerifierTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ internal class LastRunCrashVerifierTest {
2525
mockCrashFileMarker = mockk()
2626
lastRunCrashVerifier = LastRunCrashVerifier(mockCrashFileMarker)
2727
fakeWorkerThreadModule =
28-
FakeWorkerThreadModule(fakeInitModule = FakeInitModule(), testWorkerName = Worker.Background.NonIoRegWorker)
28+
FakeWorkerThreadModule(fakeInitModule = FakeInitModule(), testWorker = Worker.Background.NonIoRegWorker)
2929
worker = fakeWorkerThreadModule.backgroundWorker(Worker.Background.NonIoRegWorker)
3030
}
3131

embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/AppStartupTraceTest.kt

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
55
import io.embrace.android.embracesdk.arch.assertError
66
import io.embrace.android.embracesdk.assertions.findSpansOfType
77
import io.embrace.android.embracesdk.fakes.FakeActivity
8+
import io.embrace.android.embracesdk.fakes.FakeEmbLogger
89
import io.embrace.android.embracesdk.fakes.FakeSplashScreenActivity
910
import io.embrace.android.embracesdk.fakes.config.FakeEnabledFeatureConfig
1011
import io.embrace.android.embracesdk.fakes.config.FakeInstrumentedConfig
@@ -22,6 +23,7 @@ import io.embrace.android.embracesdk.testframework.SdkIntegrationTestRule
2223
import io.embrace.android.embracesdk.testframework.actions.EmbraceActionInterface.Companion.ACTIVITY_GAP
2324
import io.embrace.android.embracesdk.testframework.actions.EmbraceActionInterface.Companion.LIFECYCLE_EVENT_GAP
2425
import io.embrace.android.embracesdk.testframework.actions.EmbraceActionInterface.Companion.POST_ACTIVITY_ACTION_DWELL
26+
import io.embrace.android.embracesdk.testframework.actions.EmbraceSetupInterface
2527
import io.opentelemetry.sdk.trace.data.SpanData
2628
import org.junit.Assert.assertEquals
2729
import org.junit.Assert.assertNotNull
@@ -36,7 +38,11 @@ import org.robolectric.annotation.Config
3638
internal class AppStartupTraceTest {
3739
@Rule
3840
@JvmField
39-
val testRule: SdkIntegrationTestRule = SdkIntegrationTestRule()
41+
val testRule: SdkIntegrationTestRule = SdkIntegrationTestRule {
42+
EmbraceSetupInterface().apply {
43+
(overriddenInitModule.logger as FakeEmbLogger).ignoredErrors.clear()
44+
}
45+
}
4046

4147
@Test
4248
fun `startup spans recorded in foreground session when background activity is enabled`() {
@@ -307,6 +313,36 @@ internal class AppStartupTraceTest {
307313
)
308314
}
309315

316+
@Test
317+
fun `app backgrounded during cold startup while waiting for app ready`() {
318+
var backgroundTime: Long? = null
319+
testRule.runTest(
320+
instrumentedConfig = FakeInstrumentedConfig(
321+
enabledFeatures = FakeEnabledFeatureConfig(
322+
bgActivityCapture = true,
323+
endStartupWithAppReady = true
324+
)
325+
),
326+
testCaseAction = {
327+
simulateOpeningActivities(
328+
addStartupActivity = false,
329+
startInBackground = true,
330+
endInBackground = true,
331+
)
332+
backgroundTime = clock.now()
333+
},
334+
assertAction = {
335+
val session = getSingleSessionEnvelope()
336+
val spans = session.findSpansOfType(EmbType.Performance.Default).associateBy { it.name }
337+
with(checkNotNull(spans["emb-app-startup-cold"])) {
338+
assertError(ErrorCode.USER_ABANDON)
339+
assertEquals(backgroundTime, checkNotNull(endTimeNanos).nanosToMillis())
340+
}
341+
342+
}
343+
)
344+
}
345+
310346
@Test
311347
fun `warm startup waiting for app ready ended by a crash`() {
312348
var startupActivityInitMs: Long? = null
@@ -341,6 +377,40 @@ internal class AppStartupTraceTest {
341377
)
342378
}
343379

380+
@Test
381+
fun `app backgrounded during warm startup while waiting for app ready`() {
382+
var startupActivityInitMs: Long? = null
383+
var backgroundTime: Long? = null
384+
testRule.runTest(
385+
instrumentedConfig = FakeInstrumentedConfig(
386+
enabledFeatures = FakeEnabledFeatureConfig(
387+
bgActivityCapture = true,
388+
endStartupWithAppReady = true
389+
)
390+
),
391+
testCaseAction = {
392+
clock.tick(10000L)
393+
startupActivityInitMs = clock.now()
394+
simulateOpeningActivities(
395+
addStartupActivity = false,
396+
startInBackground = true,
397+
endInBackground = true,
398+
)
399+
backgroundTime = clock.now()
400+
},
401+
assertAction = {
402+
val session = getSingleSessionEnvelope()
403+
val spans = session.findSpansOfType(EmbType.Performance.Default).associateBy { it.name }
404+
with(checkNotNull(spans["emb-app-startup-warm"])) {
405+
assertError(ErrorCode.USER_ABANDON)
406+
assertEquals(startupActivityInitMs, checkNotNull(startTimeNanos).nanosToMillis())
407+
assertEquals(backgroundTime, checkNotNull(endTimeNanos).nanosToMillis())
408+
}
409+
410+
}
411+
)
412+
}
413+
344414
private fun Map<String, SpanData?>.coldAppStartupRootSpan() = getSpan("emb-app-startup-cold")
345415
private fun Map<String, SpanData?>.warmAppStartupRootSpan() = getSpan("emb-app-startup-warm")
346416
private fun Map<String, SpanData?>.processInitSpan() = getSpan("emb-process-init")

embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/FlutterInternalInterfaceTest.kt

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package io.embrace.android.embracesdk.testcases
22

33
import androidx.test.ext.junit.runners.AndroidJUnit4
44
import io.embrace.android.embracesdk.LogExceptionType
5-
import io.embrace.android.embracesdk.fakes.FakeClock
5+
import io.embrace.android.embracesdk.concurrency.BlockingScheduledExecutorService
66
import io.embrace.android.embracesdk.fakes.config.FakeInstrumentedConfig
77
import io.embrace.android.embracesdk.fakes.config.FakeProjectConfig
8-
import io.embrace.android.embracesdk.fakes.injection.FakeInitModule
9-
import io.embrace.android.embracesdk.fakes.injection.FakeWorkerThreadModule
108
import io.embrace.android.embracesdk.internal.EmbraceInternalApi
119
import io.embrace.android.embracesdk.internal.payload.AppFramework
1210
import io.embrace.android.embracesdk.internal.worker.Worker
@@ -34,19 +32,14 @@ internal class FlutterInternalInterfaceTest {
3432
appFramework = "flutter"
3533
))
3634

35+
private lateinit var executor: BlockingScheduledExecutorService
36+
3737
@Rule
3838
@JvmField
3939
val testRule: SdkIntegrationTestRule = SdkIntegrationTestRule {
40-
val clock = FakeClock(SdkIntegrationTestRule.DEFAULT_SDK_START_TIME_MS)
41-
val fakeInitModule = FakeInitModule(clock = clock)
42-
EmbraceSetupInterface(
43-
overriddenClock = clock,
44-
overriddenInitModule = fakeInitModule,
45-
overriddenWorkerThreadModule = FakeWorkerThreadModule(
46-
fakeInitModule = fakeInitModule,
47-
testWorkerName = Worker.Background.LogMessageWorker
48-
)
49-
)
40+
EmbraceSetupInterface(workerToFake = Worker.Background.LogMessageWorker).also {
41+
executor = it.getFakedWorkerExecutor()
42+
}
5043
}
5144

5245
@Test
@@ -248,9 +241,7 @@ internal class FlutterInternalInterfaceTest {
248241
}
249242

250243
private fun flushLogs() {
251-
val executor = (testRule.setup.overriddenWorkerThreadModule as FakeWorkerThreadModule).executor
252244
executor.runCurrentlyBlocked()
253-
val logOrchestrator = testRule.bootstrapper.logModule.logOrchestrator
254-
logOrchestrator.flush(false)
245+
testRule.bootstrapper.logModule.logOrchestrator.flush(false)
255246
}
256247
}

embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/LogRecordExporterTest.kt

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ package io.embrace.android.embracesdk.testcases
22

33
import androidx.test.ext.junit.runners.AndroidJUnit4
44
import io.embrace.android.embracesdk.Severity
5-
import io.embrace.android.embracesdk.assertions.returnIfConditionMet
65
import io.embrace.android.embracesdk.fakes.FakeLogRecordExporter
6+
import io.embrace.android.embracesdk.internal.arch.schema.EmbType
77
import io.embrace.android.embracesdk.testframework.SdkIntegrationTestRule
88
import org.junit.Assert.assertEquals
9-
import org.junit.Assert.assertTrue
109
import org.junit.Rule
1110
import org.junit.Test
1211
import org.junit.runner.RunWith
@@ -34,17 +33,9 @@ internal class LogRecordExporterTest {
3433
embrace.logMessage("test message", Severity.INFO)
3534
}
3635
},
37-
assertAction = {
38-
assertTrue(
39-
returnIfConditionMet(
40-
desiredValueSupplier = { true },
41-
dataProvider = { fakeLogRecordExporter.exportedLogs?.size },
42-
condition = { data ->
43-
data == 1
44-
},
45-
)
46-
)
47-
with(checkNotNull(fakeLogRecordExporter.exportedLogs?.first())) {
36+
otelExportAssertion = {
37+
val log = awaitLogs(1) { it.attributes.get(EmbType.System.Log.key.attributeKey) == EmbType.System.Log.value }
38+
with(log.single()) {
4839
assertEquals("test message", body.asString())
4940
assertEquals(logTimestampNanos, timestampEpochNanos)
5041
assertEquals(logTimestampNanos, observedTimestampEpochNanos)

embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/AeiFeatureTest.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ import android.os.Build
1010
import android.preference.PreferenceManager
1111
import androidx.test.core.app.ApplicationProvider
1212
import androidx.test.ext.junit.runners.AndroidJUnit4
13+
import io.embrace.android.embracesdk.internal.arch.schema.EmbType
1314
import io.embrace.android.embracesdk.internal.config.remote.AppExitInfoConfig
1415
import io.embrace.android.embracesdk.internal.config.remote.RemoteConfig
1516
import io.embrace.android.embracesdk.internal.payload.Log
17+
import io.embrace.android.embracesdk.internal.spans.findAttributeValue
1618
import io.embrace.android.embracesdk.testframework.SdkIntegrationTestRule
1719
import io.embrace.android.embracesdk.testframework.assertions.assertMatches
1820
import io.embrace.android.embracesdk.testframework.assertions.getLastLog
21+
import io.embrace.android.embracesdk.testframework.assertions.getLogOfType
1922
import io.mockk.every
2023
import io.mockk.mockk
2124
import org.junit.Assert.assertEquals
@@ -62,7 +65,7 @@ internal class AeiFeatureTest {
6265

6366
@Rule
6467
@JvmField
65-
val testRule = SdkIntegrationTestRule()
68+
val testRule: SdkIntegrationTestRule = SdkIntegrationTestRule()
6669

6770
private val jvmCrash = TestAeiData(
6871
ApplicationExitInfo.REASON_CRASH,
@@ -101,7 +104,7 @@ internal class AeiFeatureTest {
101104
recordSession()
102105
},
103106
assertAction = {
104-
val log = getSingleLogEnvelope().getLastLog()
107+
val log = getSingleLogEnvelope().getLogOfType(EmbType.System.Exit)
105108
log.assertContainsAeiData(jvmCrash)
106109
}
107110
)
@@ -117,7 +120,7 @@ internal class AeiFeatureTest {
117120
recordSession()
118121
},
119122
assertAction = {
120-
val log = getSingleLogEnvelope().getLastLog()
123+
val log = getSingleLogEnvelope().getLogOfType(EmbType.System.Exit)
121124
log.assertContainsAeiData(nativeCrash)
122125
}
123126
)
@@ -133,7 +136,9 @@ internal class AeiFeatureTest {
133136
recordSession()
134137
},
135138
assertAction = {
136-
val log = getSingleLogEnvelope().getLastLog()
139+
val log = getLogEnvelopes(2)
140+
.flatMap { checkNotNull(it.data.logs) }
141+
.single { it.attributes?.findAttributeValue("emb.type") == "sys.exit" }
137142
log.assertContainsAeiData(anr)
138143
}
139144
)
@@ -149,7 +154,7 @@ internal class AeiFeatureTest {
149154
recordSession()
150155
},
151156
assertAction = {
152-
val log = getSingleLogEnvelope().getLastLog()
157+
val log = getSingleLogEnvelope().getLogOfType(EmbType.System.Exit)
153158
log.assertContainsAeiData(anr)
154159
}
155160
)
@@ -172,6 +177,7 @@ internal class AeiFeatureTest {
172177
val envelopes = getLogEnvelopes(expectedSize)
173178
assertEquals(expectedSize, envelopes.size)
174179
val logs = envelopes.mapNotNull { it.data.logs?.singleOrNull() }
180+
.filter { it.attributes?.findAttributeValue("emb.type") == "sys.exit" }
175181
assertEquals(32, logs.size)
176182
}
177183
)

embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/testcases/features/AnrFeatureTest.kt

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@ package io.embrace.android.embracesdk.testcases.features
22

33
import androidx.test.ext.junit.runners.AndroidJUnit4
44
import io.embrace.android.embracesdk.concurrency.BlockingScheduledExecutorService
5-
import io.embrace.android.embracesdk.fakes.FakeClock
6-
import io.embrace.android.embracesdk.fakes.FakeConfigService
7-
import io.embrace.android.embracesdk.fakes.FakeEmbLogger
8-
import io.embrace.android.embracesdk.fakes.injection.FakeInitModule
9-
import io.embrace.android.embracesdk.fakes.injection.FakeWorkerThreadModule
105
import io.embrace.android.embracesdk.internal.anr.detection.BlockedThreadDetector
116
import io.embrace.android.embracesdk.internal.clock.nanosToMillis
12-
import io.embrace.android.embracesdk.internal.injection.createAnrModule
137
import io.embrace.android.embracesdk.internal.payload.Envelope
148
import io.embrace.android.embracesdk.internal.payload.SessionPayload
159
import io.embrace.android.embracesdk.internal.payload.Span
@@ -18,7 +12,6 @@ import io.embrace.android.embracesdk.testframework.SdkIntegrationTestRule
1812
import io.embrace.android.embracesdk.testframework.actions.EmbraceActionInterface
1913
import io.embrace.android.embracesdk.testframework.actions.EmbraceSetupInterface
2014
import io.embrace.android.embracesdk.testframework.assertions.assertMatches
21-
import java.util.concurrent.atomic.AtomicReference
2215
import org.junit.Assert.assertEquals
2316
import org.junit.Rule
2417
import org.junit.Test
@@ -40,27 +33,17 @@ internal class AnrFeatureTest {
4033
@Rule
4134
@JvmField
4235
val testRule: SdkIntegrationTestRule = SdkIntegrationTestRule {
43-
val clock = FakeClock(currentTime = START_TIME_MS)
44-
val initModule = FakeInitModule(clock, FakeEmbLogger(throwOnInternalError = false))
45-
val workerThreadModule =
46-
FakeWorkerThreadModule(initModule, Worker.Background.AnrWatchdogWorker).apply {
47-
anrMonitorThread = AtomicReference(Thread.currentThread())
48-
}
49-
anrMonitorExecutor = workerThreadModule.executor.apply { blockingMode = false }
50-
val anrModule = createAnrModule(
51-
initModule,
52-
FakeConfigService(),
53-
workerThreadModule
54-
)
55-
blockedThreadDetector = anrModule.blockedThreadDetector
56-
5736
EmbraceSetupInterface(
5837
currentTimeMs = START_TIME_MS,
59-
overriddenClock = clock,
60-
overriddenInitModule = initModule,
61-
overriddenWorkerThreadModule = workerThreadModule,
62-
fakeAnrModule = anrModule
63-
)
38+
workerToFake = Worker.Background.AnrWatchdogWorker,
39+
anrMonitoringThread = Thread.currentThread()
40+
).also {
41+
with(it) {
42+
anrMonitorExecutor = getFakedWorkerExecutor()
43+
anrMonitorExecutor.blockingMode = false
44+
blockedThreadDetector = getBlockedThreadDetector()
45+
}
46+
}
6447
}
6548

6649
@Test
@@ -183,25 +166,29 @@ internal class AnrFeatureTest {
183166
assertEquals(endTime, span.endTimeNanos?.nanosToMillis())
184167

185168
// assert span attributes
186-
span.attributes?.assertMatches(mapOf(
187-
"emb.type" to "perf.thread_blockage",
188-
"interval_code" to expectedIntervalCode
189-
))
169+
span.attributes?.assertMatches(
170+
mapOf(
171+
"emb.type" to "perf.thread_blockage",
172+
"interval_code" to expectedIntervalCode
173+
)
174+
)
190175

191176
val events = checkNotNull(span.events)
192177

193178
events.forEachIndexed { index, event ->
194179
assertEquals("perf.thread_blockage_sample", event.name)
195180

196181
// assert attributes
197-
event.attributes?.assertMatches(mapOf(
198-
"emb.type" to "perf.thread_blockage_sample",
199-
"sample_overhead" to 0,
200-
"sample_code" to when {
201-
index < MAX_SAMPLE_COUNT -> "0"
202-
else -> "1"
203-
}
204-
))
182+
event.attributes?.assertMatches(
183+
mapOf(
184+
"emb.type" to "perf.thread_blockage_sample",
185+
"sample_overhead" to 0,
186+
"sample_code" to when {
187+
index < MAX_SAMPLE_COUNT -> "0"
188+
else -> "1"
189+
}
190+
)
191+
)
205192

206193
// assert interval time
207194
val expectedTime = startTime + ANR_THRESHOLD_MS + ((index + 1) * INTERVAL_MS)

0 commit comments

Comments
 (0)