Skip to content

Commit c33bb20

Browse files
mariusc83claude
andcommitted
Reproduce RUMS-5363: duplicate view registration causes duplicate resources
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent a9d3f98 commit c33bb20

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/tracking/NavigationViewTrackingStrategyTest.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import org.mockito.kotlin.doReturn
4949
import org.mockito.kotlin.eq
5050
import org.mockito.kotlin.inOrder
5151
import org.mockito.kotlin.mock
52+
import org.mockito.kotlin.times
5253
import org.mockito.kotlin.verify
5354
import org.mockito.kotlin.verifyNoInteractions
5455
import org.mockito.kotlin.whenever
@@ -439,6 +440,48 @@ internal class NavigationViewTrackingStrategyTest {
439440
verifyNoInteractions(rumMonitor.mockInstance)
440441
}
441442

443+
// region Reproduce RUMS-5363 - duplicate listener registration causes duplicate startView calls
444+
445+
@Test
446+
fun `M register listener only once W startTracking called twice {RUMS-5363}`() {
447+
// Given - activity has started so startTracking can proceed
448+
testedStrategy.register(rumMonitor.mockSdkCore, mockActivity)
449+
testedStrategy.onActivityStarted(mockActivity)
450+
451+
// When - startTracking is called a second time (e.g. dynamic nav setup)
452+
testedStrategy.startTracking()
453+
454+
// Then - addOnDestinationChangedListener must be called exactly once.
455+
// On pre-fix code this fails: the listener is added twice because startTracking()
456+
// has no idempotency guard, so this assertion counts times(2) but we assert times(1).
457+
verify(mockNavController, times(1)).addOnDestinationChangedListener(testedStrategy)
458+
}
459+
460+
@Test
461+
fun `M call startView once W onDestinationChanged after double startTracking {RUMS-5363}`() {
462+
// Given - register the listener twice by calling startTracking twice
463+
testedStrategy.register(rumMonitor.mockSdkCore, mockActivity)
464+
testedStrategy.onActivityStarted(mockActivity)
465+
// second call re-registers the same listener instance on the NavController
466+
testedStrategy.startTracking()
467+
whenever(mockPredicate.accept(mockNavDestination)) doReturn true
468+
469+
// When - NavController fires the destination-changed event; because the listener was
470+
// registered twice, NavController iterates its list and calls onDestinationChanged twice.
471+
// We simulate that double-dispatch here to prove the downstream effect.
472+
testedStrategy.onDestinationChanged(mockNavController, mockNavDestination, null)
473+
testedStrategy.onDestinationChanged(mockNavController, mockNavDestination, null)
474+
475+
// Then - startView must be called exactly once for the destination.
476+
// On pre-fix code this fails: the double dispatch (caused by double registration) produces
477+
// two startView calls for the same destination, resulting in duplicate resource events.
478+
verify(rumMonitor.mockInstance, times(1)).startView(
479+
mockNavDestination,
480+
fakeDestinationName,
481+
mapOf(ViewScopeInstrumentationType.FRAGMENT.key.toString() to ViewScopeInstrumentationType.FRAGMENT)
482+
)
483+
}
484+
442485
// endregion
443486

444487
// FragmentLifecycleCallbacks

0 commit comments

Comments
 (0)