1
+ package com.segment.analytics.kotlin.core
2
+
3
+ import com.segment.analytics.kotlin.core.platform.EventPlugin
4
+ import com.segment.analytics.kotlin.core.platform.Plugin
5
+ import com.segment.analytics.kotlin.core.utils.StubDestinationPlugin
6
+ import com.segment.analytics.kotlin.core.utils.clearPersistentStorage
7
+ import com.segment.analytics.kotlin.core.utils.mockHTTPClient
8
+ import com.segment.analytics.kotlin.core.utils.testAnalytics
9
+ import io.mockk.coEvery
10
+ import io.mockk.coVerify
11
+ import io.mockk.mockkStatic
12
+ import kotlinx.coroutines.Job
13
+ import kotlinx.coroutines.delay
14
+ import kotlinx.coroutines.launch
15
+ import kotlinx.coroutines.test.TestScope
16
+ import kotlinx.coroutines.test.UnconfinedTestDispatcher
17
+ import kotlinx.coroutines.test.advanceTimeBy
18
+ import kotlinx.coroutines.test.advanceUntilIdle
19
+ import kotlinx.coroutines.test.runTest
20
+ import org.junit.jupiter.api.BeforeEach
21
+ import org.junit.jupiter.api.Test
22
+ import org.junit.jupiter.api.Assertions.*
23
+
24
+
25
+ class WaitingTests {
26
+
27
+ private lateinit var analytics: Analytics
28
+
29
+ private val testDispatcher = UnconfinedTestDispatcher ()
30
+
31
+ private val testScope = TestScope (testDispatcher)
32
+
33
+ @BeforeEach
34
+ fun setup () {
35
+ clearPersistentStorage()
36
+ mockHTTPClient()
37
+ val config = Configuration (
38
+ writeKey = " 123" ,
39
+ application = " Test" ,
40
+ autoAddSegmentDestination = false
41
+ )
42
+ analytics = testAnalytics(config, testScope, testDispatcher)
43
+ }
44
+
45
+ @Test
46
+ fun `test resume after timeout` () = testScope.runTest {
47
+ assertTrue(analytics.running())
48
+ analytics.pauseEventProcessing(1000 )
49
+ assertFalse(analytics.running())
50
+ advanceTimeBy(2000 )
51
+ assertTrue(analytics.running())
52
+ }
53
+
54
+ @Test
55
+ fun `test manual resume` () = testScope.runTest {
56
+ assertTrue(analytics.running())
57
+ analytics.pauseEventProcessing()
58
+ assertFalse(analytics.running())
59
+ analytics.resumeEventProcessing()
60
+ assertTrue(analytics.running())
61
+ }
62
+
63
+
64
+ @Test
65
+ fun `test pause does not dispatch state if already pause` () {
66
+ mockkStatic(" com.segment.analytics.kotlin.core.WaitingKt" )
67
+ coEvery { analytics.startProcessingAfterTimeout(any()) } returns Job ()
68
+
69
+ testScope.runTest {
70
+ analytics.pauseEventProcessing()
71
+ analytics.pauseEventProcessing()
72
+ analytics.pauseEventProcessing()
73
+ coVerify(exactly = 1 ) {
74
+ analytics.startProcessingAfterTimeout(any())
75
+ }
76
+ }
77
+ }
78
+
79
+ @Test
80
+ fun `test WaitingPlugin makes analytics to wait` () = testScope.runTest {
81
+ assertTrue(analytics.running())
82
+ val waitingPlugin = ExampleWaitingPlugin ()
83
+ analytics.add(waitingPlugin)
84
+ analytics.track(" foo" )
85
+
86
+ assertFalse(analytics.running())
87
+ assertFalse(waitingPlugin.tracked)
88
+
89
+ advanceUntilIdle()
90
+
91
+ assertTrue(analytics.running())
92
+ assertTrue(waitingPlugin.tracked)
93
+ }
94
+
95
+ @Test
96
+ fun `test timeout force resume` () = testScope.runTest {
97
+ assertTrue(analytics.running())
98
+ val waitingPlugin = ManualResumeWaitingPlugin ()
99
+ analytics.add(waitingPlugin)
100
+ analytics.track(" foo" )
101
+
102
+ assertFalse(analytics.running())
103
+ assertFalse(waitingPlugin.tracked)
104
+
105
+ advanceUntilIdle()
106
+
107
+ assertTrue(analytics.running())
108
+ assertTrue(waitingPlugin.tracked)
109
+ }
110
+
111
+ @Test
112
+ fun `test multiple WaitingPlugin` () = testScope.runTest {
113
+ assertTrue(analytics.running())
114
+ val plugin1 = ExampleWaitingPlugin ()
115
+ val plugin2 = ManualResumeWaitingPlugin ()
116
+ analytics.add(plugin1)
117
+ analytics.add(plugin2)
118
+ analytics.track(" foo" )
119
+
120
+ assertFalse(analytics.running())
121
+ assertFalse(plugin1.tracked)
122
+ assertFalse(plugin2.tracked)
123
+
124
+ plugin1.resume()
125
+ advanceTimeBy(6000 )
126
+
127
+ assertFalse(analytics.running())
128
+ assertFalse(plugin1.tracked)
129
+ assertFalse(plugin2.tracked)
130
+
131
+ plugin2.resume()
132
+ advanceUntilIdle()
133
+ assertTrue(analytics.running())
134
+ assertTrue(plugin1.tracked)
135
+ assertTrue(plugin2.tracked)
136
+ }
137
+
138
+ @Test
139
+ fun `test WaitingPlugin makes analytics to wait on DestinationPlugin` () = testScope.runTest {
140
+ assertTrue(analytics.running())
141
+ val waitingPlugin = ExampleWaitingPlugin ()
142
+ val destinationPlugin = StubDestinationPlugin ()
143
+ analytics.add(destinationPlugin)
144
+ destinationPlugin.add(waitingPlugin)
145
+ analytics.track(" foo" )
146
+
147
+ assertFalse(analytics.running())
148
+ assertFalse(waitingPlugin.tracked)
149
+
150
+ advanceUntilIdle()
151
+
152
+ assertTrue(analytics.running())
153
+ assertTrue(waitingPlugin.tracked)
154
+ }
155
+
156
+ @Test
157
+ fun `test timeout force resume on DestinationPlugin` () = testScope.runTest {
158
+ assertTrue(analytics.running())
159
+ val waitingPlugin = ManualResumeWaitingPlugin ()
160
+ val destinationPlugin = StubDestinationPlugin ()
161
+ analytics.add(destinationPlugin)
162
+ destinationPlugin.add(waitingPlugin)
163
+ analytics.track(" foo" )
164
+
165
+ assertFalse(analytics.running())
166
+ assertFalse(waitingPlugin.tracked)
167
+
168
+ advanceUntilIdle()
169
+
170
+ assertTrue(analytics.running())
171
+ assertTrue(waitingPlugin.tracked)
172
+ }
173
+
174
+ @Test
175
+ fun `test multiple WaitingPlugin on DestinationPlugin` () = testScope.runTest {
176
+ assertTrue(analytics.running())
177
+ val destinationPlugin = StubDestinationPlugin ()
178
+ analytics.add(destinationPlugin)
179
+ val plugin1 = ExampleWaitingPlugin ()
180
+ val plugin2 = ManualResumeWaitingPlugin ()
181
+ destinationPlugin.add(plugin1)
182
+ destinationPlugin.add(plugin2)
183
+ analytics.track(" foo" )
184
+
185
+ assertFalse(analytics.running())
186
+ assertFalse(plugin1.tracked)
187
+ assertFalse(plugin2.tracked)
188
+
189
+ plugin1.resume()
190
+ advanceTimeBy(6000 )
191
+
192
+ assertFalse(analytics.running())
193
+ assertFalse(plugin1.tracked)
194
+ assertFalse(plugin2.tracked)
195
+
196
+ plugin2.resume()
197
+ advanceUntilIdle()
198
+ assertTrue(analytics.running())
199
+ assertTrue(plugin1.tracked)
200
+ assertTrue(plugin2.tracked)
201
+ }
202
+
203
+ class ExampleWaitingPlugin : EventPlugin , WaitingPlugin {
204
+ override val type: Plugin .Type = Plugin .Type .Enrichment
205
+ override lateinit var analytics: Analytics
206
+ var tracked = false
207
+
208
+ override fun update (settings : Settings , type : Plugin .UpdateType ) {
209
+ if (type == Plugin .UpdateType .Initial ) {
210
+ analytics.analyticsScope.launch(analytics.analyticsDispatcher) {
211
+ delay(3000 )
212
+ resume()
213
+ }
214
+ }
215
+ }
216
+
217
+ override fun track (payload : TrackEvent ): BaseEvent ? {
218
+ tracked = true
219
+ return super .track(payload)
220
+ }
221
+ }
222
+
223
+ class ManualResumeWaitingPlugin : EventPlugin , WaitingPlugin {
224
+ override val type: Plugin .Type = Plugin .Type .Enrichment
225
+ override lateinit var analytics: Analytics
226
+ var tracked = false
227
+
228
+ override fun track (payload : TrackEvent ): BaseEvent ? {
229
+ tracked = true
230
+ return super .track(payload)
231
+ }
232
+ }
233
+ }
0 commit comments