Skip to content

Commit 503d4fc

Browse files
authored
Merge pull request #2646 from DataDog/nogorodnikov/merge-develop-into-context-sync-140525
Merge `develop` branch into feature context synchronization branch
2 parents 4431985 + cac48bb commit 503d4fc

File tree

21 files changed

+1180
-66
lines changed

21 files changed

+1180
-66
lines changed

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/system/BroadcastReceiverSystemInfoProvider.kt

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,34 @@ internal class BroadcastReceiverSystemInfoProvider(
2626
// region BroadcastReceiver
2727

2828
override fun onReceive(context: Context, intent: Intent?) {
29-
when (val action = intent?.action) {
30-
Intent.ACTION_BATTERY_CHANGED -> {
31-
handleBatteryIntent(intent)
32-
}
33-
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
34-
handlePowerSaveIntent(context)
35-
}
36-
else -> {
37-
internalLogger.log(
38-
InternalLogger.Level.DEBUG,
39-
listOf(
40-
InternalLogger.Target.MAINTAINER,
41-
InternalLogger.Target.TELEMETRY
42-
),
43-
{ "Received unknown broadcast intent: [$action]" }
44-
)
29+
try {
30+
when (val action = intent?.action) {
31+
Intent.ACTION_BATTERY_CHANGED -> {
32+
handleBatteryIntent(intent)
33+
}
34+
35+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
36+
handlePowerSaveIntent(context)
37+
}
38+
39+
else -> {
40+
internalLogger.log(
41+
InternalLogger.Level.DEBUG,
42+
listOf(
43+
InternalLogger.Target.MAINTAINER,
44+
InternalLogger.Target.TELEMETRY
45+
),
46+
{ "Received unknown broadcast intent: [$action]" }
47+
)
48+
}
4549
}
50+
} catch (@Suppress("TooGenericExceptionCaught") e: RuntimeException) {
51+
internalLogger.log(
52+
level = InternalLogger.Level.ERROR,
53+
targets = listOf(InternalLogger.Target.USER, InternalLogger.Target.TELEMETRY),
54+
messageBuilder = { ERROR_HANDLING_BROADCAST_INTENT },
55+
throwable = e
56+
)
4657
}
4758
}
4859

@@ -111,6 +122,7 @@ internal class BroadcastReceiverSystemInfoProvider(
111122
private const val DEFAULT_BATTERY_SCALE = 100
112123
private const val BATTERY_UNPLUGGED = -1
113124
private const val BATTERY_LEVEL_UNKNOWN = -1
125+
private const val ERROR_HANDLING_BROADCAST_INTENT = "Error handling system info broadcast intent."
114126

115127
private val batteryFullOrChargingStatus = setOf(
116128
SystemInfo.BatteryStatus.CHARGING,

dd-sdk-android-core/src/test/kotlin/com/datadog/android/core/internal/system/BroadcastReceiverSystemInfoProviderTest.kt

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.os.PowerManager
1313
import com.datadog.android.api.InternalLogger
1414
import com.datadog.android.utils.assertj.SystemInfoAssert.Companion.assertThat
1515
import com.datadog.android.utils.forge.Configurator
16+
import fr.xgouchet.elmyr.Forge
1617
import fr.xgouchet.elmyr.annotation.BoolForgery
1718
import fr.xgouchet.elmyr.annotation.Forgery
1819
import fr.xgouchet.elmyr.annotation.IntForgery
@@ -22,6 +23,7 @@ import fr.xgouchet.elmyr.junit5.ForgeExtension
2223
import org.junit.jupiter.api.BeforeEach
2324
import org.junit.jupiter.api.RepeatedTest
2425
import org.junit.jupiter.api.Test
26+
import org.junit.jupiter.api.assertDoesNotThrow
2527
import org.junit.jupiter.api.extension.ExtendWith
2628
import org.junit.jupiter.api.extension.Extensions
2729
import org.junit.jupiter.params.ParameterizedTest
@@ -32,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoSettings
3234
import org.mockito.kotlin.any
3335
import org.mockito.kotlin.doAnswer
3436
import org.mockito.kotlin.doReturn
37+
import org.mockito.kotlin.doThrow
3538
import org.mockito.kotlin.eq
3639
import org.mockito.kotlin.mock
3740
import org.mockito.kotlin.same
@@ -51,7 +54,7 @@ import kotlin.math.roundToInt
5154
@ForgeConfiguration(value = Configurator::class)
5255
internal class BroadcastReceiverSystemInfoProviderTest {
5356

54-
lateinit var testedProvider: BroadcastReceiverSystemInfoProvider
57+
private lateinit var testedProvider: BroadcastReceiverSystemInfoProvider
5558

5659
@Mock
5760
lateinit var mockContext: Context
@@ -442,11 +445,39 @@ internal class BroadcastReceiverSystemInfoProviderTest {
442445
assertThat(systemInfo).hasOnExternalPowerSource(false)
443446
}
444447

448+
@Test
449+
fun `M log error W onReceive { exception during intent processing }`(
450+
forge: Forge
451+
) {
452+
// Given
453+
val intent = mock<Intent>()
454+
val intentType = forge.anElementFrom(
455+
Intent.ACTION_BATTERY_CHANGED,
456+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED
457+
)
458+
whenever(intent.action) doReturn intentType
459+
when (intentType) {
460+
Intent.ACTION_BATTERY_CHANGED -> {
461+
whenever(intent.getIntExtra(any(), any())) doThrow RuntimeException()
462+
}
463+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
464+
val mockPowerManager = mock<PowerManager>()
465+
whenever(mockContext.getSystemService(Context.POWER_SERVICE)) doReturn mockPowerManager
466+
whenever(mockPowerManager.isPowerSaveMode) doThrow RuntimeException()
467+
}
468+
}
469+
470+
// When + Then
471+
assertDoesNotThrow {
472+
testedProvider.onReceive(mockContext, intent)
473+
}
474+
}
475+
445476
// endregion
446477

447478
// region Internal
448479

449-
fun SystemInfo.BatteryStatus.androidStatus(): Int {
480+
private fun SystemInfo.BatteryStatus.androidStatus(): Int {
450481
return when (this) {
451482
SystemInfo.BatteryStatus.UNKNOWN -> BatteryManager.BATTERY_STATUS_UNKNOWN
452483
SystemInfo.BatteryStatus.CHARGING -> BatteryManager.BATTERY_STATUS_CHARGING

dd-sdk-android-core/src/test/kotlin/com/datadog/android/utils/forge/Configurator.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ internal class Configurator :
2424
forge.addFactory(CustomAttributesForgeryFactory())
2525
forge.addFactory(ConfigurationForgeryFactory())
2626
forge.addFactory(ConfigurationCoreForgeryFactory())
27-
forge.addFactory(ConfigurationForgeryFactory())
2827
forge.addFactory(FilePersistenceConfigForgeryFactory())
2928
forge.addFactory(AndroidInfoProviderForgeryFactory())
3029
forge.addFactory(FeatureStorageConfigurationForgeryFactory())

features/dd-sdk-android-trace/src/main/java/com/datadog/opentracing/PendingTrace.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,22 @@
1111
import com.datadog.android.api.InternalLogger;
1212
import com.datadog.exec.CommonTaskExecutor;
1313
import com.datadog.exec.CommonTaskExecutor.Task;
14-
import com.datadog.opentracing.scopemanager.ContinuableScope;
1514
import com.datadog.legacy.trace.common.util.Clock;
15+
import com.datadog.opentracing.scopemanager.ContinuableScope;
1616

1717
import java.io.Closeable;
1818
import java.lang.ref.Reference;
1919
import java.lang.ref.ReferenceQueue;
2020
import java.lang.ref.WeakReference;
2121
import java.math.BigInteger;
22-
import java.util.*;
22+
import java.util.ArrayList;
23+
import java.util.Collections;
24+
import java.util.HashMap;
25+
import java.util.Iterator;
26+
import java.util.LinkedList;
27+
import java.util.List;
28+
import java.util.Map;
29+
import java.util.Set;
2330
import java.util.concurrent.ConcurrentHashMap;
2431
import java.util.concurrent.TimeUnit;
2532
import java.util.concurrent.atomic.AtomicBoolean;
@@ -355,7 +362,7 @@ public synchronized boolean clean() {
355362
@Override
356363
public void addFirst(final DDSpan span) {
357364
synchronized (this) {
358-
super.addFirst(span);
365+
super.add(0, span);
359366
}
360367
completedSpanCount.incrementAndGet();
361368
}

reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/BaseTest.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ abstract class BaseTest {
1414
companion object {
1515
internal val LONG_WAIT_MS = TimeUnit.SECONDS.toMillis(60)
1616
internal val MEDIUM_WAIT_MS = TimeUnit.SECONDS.toMillis(30)
17+
18+
// TODO RUM-9917 Avoid using unconditional wait locks
19+
// to align with UploadFrequency max value + 1s for async execution
20+
internal val UPLOAD_CYCLE_MAX_WAIT_MS = TimeUnit.SECONDS.toMillis(6)
1721
internal const val SHORT_WAIT_MS = 500L
1822
}
1923
}

reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/FeatureScopeTest.kt

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import org.junit.Before
3131
import org.junit.Rule
3232
import org.junit.Test
3333
import org.junit.runner.RunWith
34+
import java.util.concurrent.CountDownLatch
35+
import java.util.concurrent.TimeUnit
3436

3537
/**
3638
* Instrumentation tests for the feature scope.
@@ -211,6 +213,7 @@ class FeatureScopeTest : MockServerTest() {
211213
) as InternalSdkCore
212214
testedInternalSdkCore.registerFeature(stubFeature)
213215
val featureScope = testedInternalSdkCore.getFeature(fakeFeatureName)
216+
val countDownLatch = CountDownLatch(fakeBatchData.size)
214217

215218
// When
216219
checkNotNull(featureScope)
@@ -222,12 +225,15 @@ class FeatureScopeTest : MockServerTest() {
222225
fakeBatchMetadata,
223226
eventType
224227
)
228+
countDownLatch.countDown()
225229
}
226230
}
227231
}
228232

229233
// Then
230-
Thread.sleep(MEDIUM_WAIT_MS)
234+
countDownLatch.await(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
235+
// TODO RUM-9917 Avoid using unconditional wait locks
236+
Thread.sleep(UPLOAD_CYCLE_MAX_WAIT_MS)
231237
MockWebServerAssert.assertThat(getMockServerWrapper())
232238
.withConfiguration(fakeConfiguration)
233239
.withTrackingConsent(trackingConsent)
@@ -249,6 +255,7 @@ class FeatureScopeTest : MockServerTest() {
249255
) as InternalSdkCore
250256
testedInternalSdkCore.registerFeature(stubFeature)
251257
val featureScope = testedInternalSdkCore.getFeature(fakeFeatureName)
258+
val countDownLatch = CountDownLatch(fakeBatchData.size)
252259

253260
// When
254261
checkNotNull(featureScope)
@@ -260,12 +267,15 @@ class FeatureScopeTest : MockServerTest() {
260267
fakeBatchMetadata,
261268
eventType
262269
)
270+
countDownLatch.countDown()
263271
}
264272
}
265273
}
266274

267275
// Then
268-
Thread.sleep(MEDIUM_WAIT_MS)
276+
countDownLatch.await(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
277+
// TODO RUM-9917 Avoid using unconditional wait locks
278+
Thread.sleep(UPLOAD_CYCLE_MAX_WAIT_MS)
269279
MockWebServerAssert.assertThat(getMockServerWrapper())
270280
.withConfiguration(fakeConfiguration)
271281
.withTrackingConsent(trackingConsent)
@@ -284,6 +294,7 @@ class FeatureScopeTest : MockServerTest() {
284294
testedInternalSdkCore.registerFeature(stubFeature)
285295
val featureScope = testedInternalSdkCore.getFeature(fakeFeatureName)
286296
checkNotNull(featureScope)
297+
val countDownLatch = CountDownLatch(fakeBatchData.size)
287298
featureScope.withWriteContext { _, writeScope ->
288299
fakeBatchData.forEach { rawBatchEvent ->
289300
writeScope {
@@ -292,6 +303,7 @@ class FeatureScopeTest : MockServerTest() {
292303
fakeBatchMetadata,
293304
eventType
294305
)
306+
countDownLatch.countDown()
295307
}
296308
}
297309
}
@@ -300,7 +312,13 @@ class FeatureScopeTest : MockServerTest() {
300312
Datadog.setTrackingConsent(TrackingConsent.NOT_GRANTED)
301313

302314
// Then
303-
Thread.sleep(MEDIUM_WAIT_MS)
315+
countDownLatch.await(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
316+
with(testedInternalSdkCore.getPersistenceExecutorService()) {
317+
shutdown()
318+
awaitTermination(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
319+
}
320+
// TODO RUM-9917 Avoid using unconditional wait locks
321+
Thread.sleep(UPLOAD_CYCLE_MAX_WAIT_MS)
304322
MockWebServerAssert.assertThat(getMockServerWrapper())
305323
.withConfiguration(fakeConfiguration)
306324
.withTrackingConsent(trackingConsent)
@@ -323,6 +341,7 @@ class FeatureScopeTest : MockServerTest() {
323341
testedInternalSdkCore.registerFeature(stubFeature)
324342
val featureScope = testedInternalSdkCore.getFeature(fakeFeatureName)
325343
checkNotNull(featureScope)
344+
val countDownLatch = CountDownLatch(fakeBatchData.size)
326345
featureScope.withWriteContext { _, writeScope ->
327346
fakeBatchData.forEach { rawBatchEvent ->
328347
writeScope {
@@ -331,6 +350,7 @@ class FeatureScopeTest : MockServerTest() {
331350
fakeBatchMetadata,
332351
eventType
333352
)
353+
countDownLatch.countDown()
334354
}
335355
}
336356
}
@@ -340,7 +360,13 @@ class FeatureScopeTest : MockServerTest() {
340360
Datadog.setTrackingConsent(TrackingConsent.GRANTED)
341361

342362
// Then
343-
Thread.sleep(MEDIUM_WAIT_MS)
363+
countDownLatch.await(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
364+
with(testedInternalSdkCore.getPersistenceExecutorService()) {
365+
shutdown()
366+
awaitTermination(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
367+
}
368+
// TODO RUM-9917 Avoid using unconditional wait locks
369+
Thread.sleep(UPLOAD_CYCLE_MAX_WAIT_MS)
344370
MockWebServerAssert.assertThat(getMockServerWrapper())
345371
.withConfiguration(fakeConfiguration)
346372
.withTrackingConsent(trackingConsent)
@@ -364,6 +390,7 @@ class FeatureScopeTest : MockServerTest() {
364390
val featureScope = testedInternalSdkCore.getFeature(fakeFeatureName)
365391
checkNotNull(featureScope)
366392
Datadog.stopInstance()
393+
val countDownLatch = CountDownLatch(fakeBatchData.size)
367394

368395
// When
369396
featureScope.withWriteContext { _, writeScope ->
@@ -374,12 +401,15 @@ class FeatureScopeTest : MockServerTest() {
374401
fakeBatchMetadata,
375402
eventType
376403
)
404+
countDownLatch.countDown()
377405
}
378406
}
379407
}
380408

381409
// Then
382-
Thread.sleep(MEDIUM_WAIT_MS)
410+
countDownLatch.await(MEDIUM_WAIT_MS, TimeUnit.MILLISECONDS)
411+
// TODO RUM-9917 Avoid using unconditional wait locks
412+
Thread.sleep(UPLOAD_CYCLE_MAX_WAIT_MS)
383413
MockWebServerAssert.assertThat(getMockServerWrapper())
384414
.withConfiguration(fakeConfiguration)
385415
.withTrackingConsent(trackingConsent)

0 commit comments

Comments
 (0)