Skip to content

Commit 5c0b4d6

Browse files
committed
detekt safe
1 parent e444714 commit 5c0b4d6

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

detekt_custom_safe_calls.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ datadog:
449449
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.api.SdkCore?)"
450450
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.api.feature.FeatureEventReceiver?)"
451451
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.flags.internal.repository.DefaultFlagsRepository.FlagsState?)"
452+
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.flags.model.FlagsClientState?)"
452453
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.flags.model.ProviderContext?)"
453454
- "java.util.concurrent.atomic.AtomicReference.constructor(com.datadog.android.rum.internal.domain.RumContext?)"
454455
- "java.util.concurrent.atomic.AtomicReference.constructor(kotlin.collections.Map?)"
@@ -461,6 +462,7 @@ datadog:
461462
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.android.rum.internal.domain.RumContext?)"
462463
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.android.trace.api.tracer.DatadogTracer?)"
463464
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.android.flags.internal.repository.DefaultFlagsRepository.FlagsState?)"
465+
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.android.flags.model.FlagsClientState?)"
464466
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.android.flags.model.ProviderContext?)"
465467
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI?)"
466468
- "java.util.concurrent.atomic.AtomicReference.set(com.datadog.trace.core.CoreTracer?)"
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
7+
package com.datadog.android.flags.internal
8+
9+
import com.datadog.android.flags.FlagsStateListener
10+
import com.datadog.android.flags.model.FlagsClientState
11+
import com.datadog.android.internal.utils.DDCoreSubscription
12+
import org.assertj.core.api.Assertions.assertThat
13+
import org.junit.jupiter.api.BeforeEach
14+
import org.junit.jupiter.api.Test
15+
import org.junit.jupiter.api.extension.ExtendWith
16+
import org.mockito.Mock
17+
import org.mockito.junit.jupiter.MockitoExtension
18+
import org.mockito.junit.jupiter.MockitoSettings
19+
import org.mockito.kotlin.argumentCaptor
20+
import org.mockito.kotlin.verify
21+
import org.mockito.kotlin.verifyNoInteractions
22+
import org.mockito.quality.Strictness
23+
24+
@ExtendWith(MockitoExtension::class)
25+
@MockitoSettings(strictness = Strictness.LENIENT)
26+
internal class FlagsStateChannelTest {
27+
28+
@Mock
29+
lateinit var mockListener: FlagsStateListener
30+
31+
private lateinit var testedChannel: FlagsStateChannel
32+
33+
@BeforeEach
34+
fun `set up`() {
35+
testedChannel = FlagsStateChannel(DDCoreSubscription.create())
36+
}
37+
38+
// region notifyNotReady
39+
40+
@Test
41+
fun `M notify listeners with NOT_READY W notifyNotReady()`() {
42+
// Given
43+
testedChannel.addListener(mockListener)
44+
45+
// When
46+
testedChannel.notifyNotReady()
47+
48+
// Then
49+
verify(mockListener).onStateChanged(FlagsClientState.NOT_READY, null)
50+
}
51+
52+
// endregion
53+
54+
// region notifyReady
55+
56+
@Test
57+
fun `M notify listeners with READY W notifyReady()`() {
58+
// Given
59+
testedChannel.addListener(mockListener)
60+
61+
// When
62+
testedChannel.notifyReady()
63+
64+
// Then
65+
verify(mockListener).onStateChanged(FlagsClientState.READY, null)
66+
}
67+
68+
// endregion
69+
70+
// region notifyReconciling
71+
72+
@Test
73+
fun `M notify listeners with RECONCILING W notifyReconciling()`() {
74+
// Given
75+
testedChannel.addListener(mockListener)
76+
77+
// When
78+
testedChannel.notifyReconciling()
79+
80+
// Then
81+
verify(mockListener).onStateChanged(FlagsClientState.RECONCILING, null)
82+
}
83+
84+
// endregion
85+
86+
// region notifyError
87+
88+
@Test
89+
fun `M notify listeners with ERROR and null W notifyError() {no error provided}`() {
90+
// Given
91+
testedChannel.addListener(mockListener)
92+
93+
// When
94+
testedChannel.notifyError()
95+
96+
// Then
97+
verify(mockListener).onStateChanged(FlagsClientState.ERROR, null)
98+
}
99+
100+
@Test
101+
fun `M notify listeners with ERROR and throwable W notifyError() {error provided}`() {
102+
// Given
103+
testedChannel.addListener(mockListener)
104+
val fakeError = RuntimeException("Test error")
105+
106+
// When
107+
testedChannel.notifyError(fakeError)
108+
109+
// Then
110+
verify(mockListener).onStateChanged(FlagsClientState.ERROR, fakeError)
111+
}
112+
113+
// endregion
114+
115+
// region addListener / removeListener
116+
117+
@Test
118+
fun `M notify listener W addListener() and notify`() {
119+
// Given
120+
testedChannel.addListener(mockListener)
121+
122+
// When
123+
testedChannel.notifyReady()
124+
125+
// Then
126+
verify(mockListener).onStateChanged(FlagsClientState.READY, null)
127+
}
128+
129+
@Test
130+
fun `M not notify listener W removeListener() and notify`() {
131+
// Given
132+
testedChannel.addListener(mockListener)
133+
testedChannel.removeListener(mockListener)
134+
135+
// When
136+
testedChannel.notifyReady()
137+
138+
// Then
139+
verifyNoInteractions(mockListener)
140+
}
141+
142+
@Test
143+
fun `M notify all listeners W multiple listeners registered`() {
144+
// Given
145+
val mockListener2 = org.mockito.Mockito.mock(FlagsStateListener::class.java)
146+
testedChannel.addListener(mockListener)
147+
testedChannel.addListener(mockListener2)
148+
149+
// When
150+
testedChannel.notifyReady()
151+
152+
// Then
153+
verify(mockListener).onStateChanged(FlagsClientState.READY, null)
154+
verify(mockListener2).onStateChanged(FlagsClientState.READY, null)
155+
}
156+
157+
@Test
158+
fun `M notify listeners in order W multiple state transitions`() {
159+
// Given
160+
testedChannel.addListener(mockListener)
161+
162+
// When
163+
testedChannel.notifyNotReady()
164+
testedChannel.notifyReconciling()
165+
testedChannel.notifyReady()
166+
167+
// Then
168+
val captor = argumentCaptor<FlagsClientState>()
169+
verify(mockListener, org.mockito.kotlin.times(3)).onStateChanged(captor.capture(), org.mockito.kotlin.any())
170+
171+
assertThat(captor.allValues).containsExactly(
172+
FlagsClientState.NOT_READY,
173+
FlagsClientState.RECONCILING,
174+
FlagsClientState.READY
175+
)
176+
}
177+
178+
// endregion
179+
}

0 commit comments

Comments
 (0)