@@ -10,6 +10,10 @@ abstract class MainDispatcherTestBase: TestBase() {
10
10
11
11
open fun shouldSkipTesting (): Boolean = false
12
12
13
+ open suspend fun spinTest (testBody : Job ) {
14
+ testBody.join()
15
+ }
16
+
13
17
abstract fun isMainThread (): Boolean?
14
18
15
19
abstract fun scheduleOnMainQueue (block : () -> Unit )
@@ -19,7 +23,10 @@ abstract class MainDispatcherTestBase: TestBase() {
19
23
// written as a block body to make the need to return `TestResult` explicit
20
24
return runTest {
21
25
if (shouldSkipTesting()) return @runTest
22
- block()
26
+ val testBody = launch(Dispatchers .Default ) {
27
+ block()
28
+ }
29
+ spinTest(testBody)
23
30
}
24
31
}
25
32
@@ -52,25 +59,6 @@ abstract class MainDispatcherTestBase: TestBase() {
52
59
assertNotEquals(Dispatchers .Main , Dispatchers .Main .immediate)
53
60
}
54
61
55
- /* * Tests that after a delay, the execution gets back to the main thread. */
56
- @Test
57
- @Ignore // TODO: hangs on Android
58
- fun testDelay () = runTestOrSkip {
59
- expect(1 )
60
- checkNotMainThread()
61
- scheduleOnMainQueue { expect(2 ) }
62
- withContext(Dispatchers .Main ) {
63
- checkIsMainThread()
64
- expect(3 )
65
- scheduleOnMainQueue { expect(4 ) }
66
- delay(100 )
67
- checkIsMainThread()
68
- expect(5 )
69
- }
70
- checkNotMainThread()
71
- finish(6 )
72
- }
73
-
74
62
/* * Tests that [Dispatchers.Main] shares its queue with [MainCoroutineDispatcher.immediate]. */
75
63
@Test
76
64
fun testImmediateDispatcherYield () = runTestOrSkip {
@@ -90,82 +78,6 @@ abstract class MainDispatcherTestBase: TestBase() {
90
78
finish(6 )
91
79
}
92
80
93
- /* * Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much slower. */
94
- @Test
95
- @Ignore // TODO: hangs on Android
96
- fun testWithTimeoutContextDelayNoTimeout () = runTestOrSkip {
97
- expect(1 )
98
- withTimeout(1000 ) {
99
- withContext(Dispatchers .Main ) {
100
- checkIsMainThread()
101
- expect(2 )
102
- delay(100 )
103
- checkIsMainThread()
104
- expect(3 )
105
- }
106
- }
107
- checkNotMainThread()
108
- finish(4 )
109
- }
110
-
111
- /* * Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much faster. */
112
- @Test
113
- @Ignore // TODO: hangs on Android
114
- fun testWithTimeoutContextDelayTimeout () = runTestOrSkip {
115
- expect(1 )
116
- assertFailsWith<TimeoutCancellationException > {
117
- withTimeout(300 ) {
118
- withContext(Dispatchers .Main ) {
119
- checkIsMainThread()
120
- expect(2 )
121
- delay(1000 )
122
- expectUnreached()
123
- }
124
- }
125
- expectUnreached()
126
- }
127
- checkNotMainThread()
128
- finish(3 )
129
- }
130
-
131
- /* * Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much faster. */
132
- @Test
133
- @Ignore // TODO: hangs on Android
134
- fun testWithContextTimeoutDelayNoTimeout () = runTestOrSkip {
135
- expect(1 )
136
- withContext(Dispatchers .Main ) {
137
- withTimeout(1000 ) {
138
- checkIsMainThread()
139
- expect(2 )
140
- delay(100 )
141
- checkIsMainThread()
142
- expect(3 )
143
- }
144
- }
145
- checkNotMainThread()
146
- finish(4 )
147
- }
148
-
149
- /* * Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much slower. */
150
- @Test
151
- @Ignore // TODO: hangs on Android
152
- fun testWithContextTimeoutDelayTimeout () = runTestOrSkip {
153
- expect(1 )
154
- assertFailsWith<TimeoutCancellationException > {
155
- withContext(Dispatchers .Main ) {
156
- withTimeout(100 ) {
157
- checkIsMainThread()
158
- expect(2 )
159
- delay(1000 )
160
- expectUnreached()
161
- }
162
- }
163
- expectUnreached()
164
- }
165
- checkNotMainThread()
166
- finish(3 )
167
- }
168
-
169
81
/* * Tests that entering [MainCoroutineDispatcher.immediate] from [Dispatchers.Main] happens immediately. */
170
82
@Test
171
83
fun testEnteringImmediateFromMain () = runTestOrSkip {
@@ -183,23 +95,22 @@ abstract class MainDispatcherTestBase: TestBase() {
183
95
/* * Tests that dispatching to [MainCoroutineDispatcher.immediate] is required from and only from dispatchers
184
96
* other than the main dispatchers and that it's always required for [Dispatchers.Main] itself. */
185
97
@Test
186
- @Ignore // TODO: hangs on Android
187
98
fun testDispatchRequirements () = runTestOrSkip {
188
- withContext(Dispatchers .Default ) {
189
- assertTrue(Dispatchers .Main .immediate.isDispatchNeeded(currentCoroutineContext()))
190
- assertTrue(Dispatchers .Main .isDispatchNeeded(currentCoroutineContext()))
191
- assertTrue(Dispatchers .Default .isDispatchNeeded(currentCoroutineContext()))
192
- withContext(Dispatchers .Main ) {
193
- assertFalse(Dispatchers .Main .immediate.isDispatchNeeded(currentCoroutineContext()))
194
- assertTrue(Dispatchers .Main .isDispatchNeeded(currentCoroutineContext()))
195
- assertTrue(Dispatchers .Default .isDispatchNeeded(currentCoroutineContext()))
196
- withContext(Dispatchers .Main .immediate) {
197
- assertFalse(Dispatchers .Main .immediate.isDispatchNeeded(currentCoroutineContext()))
198
- assertTrue(Dispatchers .Main .isDispatchNeeded(currentCoroutineContext()))
199
- assertTrue(Dispatchers .Default .isDispatchNeeded(currentCoroutineContext()))
200
- }
99
+ checkDispatchRequirements()
100
+ withContext(Dispatchers .Main ) {
101
+ checkDispatchRequirements()
102
+ withContext(Dispatchers .Main .immediate) {
103
+ checkDispatchRequirements()
201
104
}
105
+ checkDispatchRequirements()
202
106
}
107
+ checkDispatchRequirements()
108
+ }
109
+
110
+ private suspend fun checkDispatchRequirements () {
111
+ isMainThread()?.let { assertNotEquals(it, Dispatchers .Main .immediate.isDispatchNeeded(currentCoroutineContext())) }
112
+ assertTrue(Dispatchers .Main .isDispatchNeeded(currentCoroutineContext()))
113
+ assertTrue(Dispatchers .Default .isDispatchNeeded(currentCoroutineContext()))
203
114
}
204
115
205
116
/* * Tests that launching a coroutine in [MainScope] will execute it in the main thread. */
@@ -258,6 +169,98 @@ abstract class MainDispatcherTestBase: TestBase() {
258
169
}
259
170
}
260
171
172
+ abstract class WithRealTimeDelay : MainDispatcherTestBase () {
173
+ /* * Tests that after a delay, the execution gets back to the main thread. */
174
+ @Test
175
+ fun testDelay () = runTestOrSkip {
176
+ expect(1 )
177
+ checkNotMainThread()
178
+ scheduleOnMainQueue { expect(2 ) }
179
+ withContext(Dispatchers .Main ) {
180
+ checkIsMainThread()
181
+ expect(3 )
182
+ scheduleOnMainQueue { expect(4 ) }
183
+ delay(100 )
184
+ checkIsMainThread()
185
+ expect(5 )
186
+ }
187
+ checkNotMainThread()
188
+ finish(6 )
189
+ }
190
+
191
+ /* * Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much slower. */
192
+ @Test
193
+ fun testWithTimeoutContextDelayNoTimeout () = runTestOrSkip {
194
+ expect(1 )
195
+ withTimeout(1000 ) {
196
+ withContext(Dispatchers .Main ) {
197
+ checkIsMainThread()
198
+ expect(2 )
199
+ delay(100 )
200
+ checkIsMainThread()
201
+ expect(3 )
202
+ }
203
+ }
204
+ checkNotMainThread()
205
+ finish(4 )
206
+ }
207
+
208
+ /* * Tests that [Dispatchers.Main] is in agreement with the default time source: it's not much faster. */
209
+ @Test
210
+ fun testWithTimeoutContextDelayTimeout () = runTestOrSkip {
211
+ expect(1 )
212
+ assertFailsWith<TimeoutCancellationException > {
213
+ withTimeout(300 ) {
214
+ withContext(Dispatchers .Main ) {
215
+ checkIsMainThread()
216
+ expect(2 )
217
+ delay(1000 )
218
+ expectUnreached()
219
+ }
220
+ }
221
+ expectUnreached()
222
+ }
223
+ checkNotMainThread()
224
+ finish(3 )
225
+ }
226
+
227
+ /* * Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much faster. */
228
+ @Test
229
+ fun testWithContextTimeoutDelayNoTimeout () = runTestOrSkip {
230
+ expect(1 )
231
+ withContext(Dispatchers .Main ) {
232
+ withTimeout(1000 ) {
233
+ checkIsMainThread()
234
+ expect(2 )
235
+ delay(100 )
236
+ checkIsMainThread()
237
+ expect(3 )
238
+ }
239
+ }
240
+ checkNotMainThread()
241
+ finish(4 )
242
+ }
243
+
244
+ /* * Tests that the timeout of [Dispatchers.Main] is in agreement with its [delay]: it's not much slower. */
245
+ @Test
246
+ fun testWithContextTimeoutDelayTimeout () = runTestOrSkip {
247
+ expect(1 )
248
+ assertFailsWith<TimeoutCancellationException > {
249
+ withContext(Dispatchers .Main ) {
250
+ withTimeout(100 ) {
251
+ checkIsMainThread()
252
+ expect(2 )
253
+ delay(1000 )
254
+ expectUnreached()
255
+ }
256
+ }
257
+ expectUnreached()
258
+ }
259
+ checkNotMainThread()
260
+ finish(3 )
261
+ }
262
+ }
263
+
261
264
fun checkIsMainThread () { isMainThread()?.let { check(it) } }
262
265
fun checkNotMainThread () { isMainThread()?.let { check(! it) } }
263
266
}
0 commit comments