• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines.test
6 
7 import kotlinx.coroutines.*
8 import kotlin.test.*
9 
10 @Suppress("DEPRECATION")
11 class TestRunBlockingTest {
12 
13     @Test
14     fun delay_advancesTimeAutomatically() = runBlockingTest {
15         assertRunsFast {
16             delay(SLOW)
17         }
18     }
19 
20     @Test
21     fun callingSuspendWithDelay_advancesAutomatically() = runBlockingTest {
22         suspend fun withDelay(): Int {
23             delay(SLOW)
24             return 3
25         }
26 
27         assertRunsFast {
28             assertEquals(3, withDelay())
29         }
30     }
31 
32     @Test
33     fun launch_advancesAutomatically()  = runBlockingTest {
34         val job = launch {
35             delay(SLOW)
36         }
37         assertRunsFast {
38             job.join()
39             assertTrue(job.isCompleted)
40         }
41     }
42 
43     @Test
44     fun async_advancesAutomatically() = runBlockingTest {
45         val deferred = async {
46             delay(SLOW)
47             3
48         }
49 
50         assertRunsFast {
51             assertEquals(3, deferred.await())
52         }
53     }
54 
55     @Test
56     fun whenUsingTimeout_triggersWhenDelayed() {
57         assertFailsWith<TimeoutCancellationException> {
58             runBlockingTest {
59                 assertRunsFast {
60                     withTimeout(SLOW) {
61                         delay(SLOW)
62                     }
63                 }
64             }
65         }
66     }
67 
68     @Test
69     fun whenUsingTimeout_doesNotTriggerWhenFast() = runBlockingTest {
70         assertRunsFast {
71             withTimeout(SLOW) {
72                 delay(0)
73             }
74         }
75     }
76 
77     @Test
78     fun whenUsingTimeout_triggersWhenWaiting() {
79         assertFailsWith<TimeoutCancellationException> {
80             runBlockingTest {
81                 val uncompleted = CompletableDeferred<Unit>()
82                 assertRunsFast {
83                     withTimeout(SLOW) {
84                         uncompleted.await()
85                     }
86                 }
87             }
88         }
89     }
90 
91     @Test
92     fun whenUsingTimeout_doesNotTriggerWhenComplete() = runBlockingTest {
93         val completed = CompletableDeferred<Unit>()
94         assertRunsFast {
95             completed.complete(Unit)
96             withTimeout(SLOW) {
97                 completed.await()
98             }
99         }
100     }
101 
102     @Test
103     fun testDelayInAsync_withAwait() = runBlockingTest {
104         assertRunsFast {
105             val deferred = async {
106                 delay(SLOW)
107                 3
108             }
109             assertEquals(3, deferred.await())
110         }
111     }
112 
113     @Test
114     fun whenUsingTimeout_inAsync_triggersWhenDelayed() {
115         assertFailsWith<TimeoutCancellationException> {
116             runBlockingTest {
117                 val deferred = async {
118                     withTimeout(SLOW) {
119                         delay(SLOW)
120                     }
121                 }
122 
123                 assertRunsFast {
124                     deferred.await()
125                 }
126             }
127         }
128     }
129 
130     @Test
131     fun whenUsingTimeout_inAsync_doesNotTriggerWhenNotDelayed() = runBlockingTest {
132         val deferred = async {
133             withTimeout(SLOW) {
134                 delay(0)
135             }
136         }
137 
138         assertRunsFast {
139             deferred.await()
140         }
141     }
142 
143     @Test
144     fun whenUsingTimeout_inLaunch_triggersWhenDelayed() {
145         assertFailsWith<TimeoutCancellationException> {
146             runBlockingTest {
147                 val job = launch {
148                     withTimeout(1) {
149                         delay(SLOW + 1)
150                     }
151                 }
152 
153                 assertRunsFast {
154                     job.join()
155                     throw job.getCancellationException()
156                 }
157             }
158         }
159     }
160 
161     @Test
162     fun whenUsingTimeout_inLaunch_doesNotTriggerWhenNotDelayed() = runBlockingTest {
163         val job = launch {
164             withTimeout(SLOW) {
165                 delay(0)
166             }
167         }
168 
169         assertRunsFast {
170             job.join()
171             assertTrue(job.isCompleted)
172         }
173     }
174 
175     @Test
176     fun throwingException_throws() {
177         assertFailsWith<IllegalArgumentException> {
178             runBlockingTest {
179                 assertRunsFast {
180                     delay(SLOW)
181                     throw IllegalArgumentException("Test")
182                 }
183             }
184         }
185     }
186 
187     @Test
188     fun throwingException_inLaunch_throws() {
189         assertFailsWith<IllegalArgumentException> {
190             runBlockingTest {
191                 val job = launch {
192                     delay(SLOW)
193                     throw IllegalArgumentException("Test")
194                 }
195 
196                 assertRunsFast {
197                     job.join()
198                     throw job.getCancellationException().cause ?: AssertionError("expected exception")
199                 }
200             }
201         }
202     }
203 
204     @Test
205     fun throwingException__inAsync_throws() {
206         assertFailsWith<IllegalArgumentException> {
207             runBlockingTest {
208                 val deferred: Deferred<Unit> = async {
209                     delay(SLOW)
210                     throw IllegalArgumentException("Test")
211                 }
212 
213                 assertRunsFast {
214                     deferred.await()
215                 }
216             }
217         }
218     }
219 
220     @Test
221     fun callingLaunchFunction_executesLaunchBlockImmediately() = runBlockingTest {
222         assertRunsFast {
223             var executed = false
224             launch {
225                 delay(SLOW)
226                 executed = true
227             }
228 
229             delay(SLOW)
230             assertTrue(executed)
231         }
232     }
233 
234     @Test
235     fun callingAsyncFunction_executesAsyncBlockImmediately() = runBlockingTest {
236         assertRunsFast {
237             var executed = false
238             val deferred = async {
239                 delay(SLOW)
240                 executed = true
241             }
242             advanceTimeBy(SLOW)
243 
244             assertTrue(deferred.isCompleted)
245             assertTrue(executed)
246         }
247     }
248 
249     @Test
250     fun nestingBuilders_executesSecondLevelImmediately() = runBlockingTest {
251         assertRunsFast {
252             var levels = 0
253             launch {
254                 delay(SLOW)
255                 levels++
256                 launch {
257                     delay(SLOW)
258                     levels++
259                 }
260             }
261             advanceUntilIdle()
262 
263             assertEquals(2, levels)
264         }
265     }
266 
267     @Test
268     fun testCancellationException() = runBlockingTest {
269         var actual: CancellationException? = null
270         val uncompleted = CompletableDeferred<Unit>()
271         val job = launch {
272             actual = kotlin.runCatching { uncompleted.await() }.exceptionOrNull() as? CancellationException
273         }
274 
275         assertNull(actual)
276         job.cancel()
277         assertNotNull(actual)
278     }
279 
280     @Test
281     fun testCancellationException_notThrown() = runBlockingTest {
282         val uncompleted = CompletableDeferred<Unit>()
283         val job = launch {
284             uncompleted.await()
285         }
286 
287         job.cancel()
288         job.join()
289     }
290 
291     @Test
292     fun whenACoroutineLeaks_errorIsThrown() {
293         assertFailsWith<UncompletedCoroutinesError> {
294             runBlockingTest {
295                 val uncompleted = CompletableDeferred<Unit>()
296                 launch {
297                     uncompleted.await()
298                 }
299             }
300         }
301     }
302 
303     @Test
304     fun runBlockingTestBuilder_throwsOnBadDispatcher() {
305         assertFailsWith<IllegalArgumentException> {
306             runBlockingTest(Dispatchers.Default) {
307 
308             }
309         }
310     }
311 
312     @Test
313     fun runBlockingTestBuilder_throwsOnBadHandler() {
314         assertFailsWith<IllegalArgumentException> {
315             runBlockingTest(CoroutineExceptionHandler { _, _ -> }) {
316 
317             }
318         }
319     }
320 
321     @Test
322     fun pauseDispatcher_disablesAutoAdvance_forCurrent() = runBlockingTest {
323         var mutable = 0
324         pauseDispatcher {
325             launch {
326                 mutable++
327             }
328             assertEquals(0, mutable)
329             runCurrent()
330             assertEquals(1, mutable)
331         }
332     }
333 
334     @Test
335     fun pauseDispatcher_disablesAutoAdvance_forDelay() = runBlockingTest {
336         var mutable = 0
337         pauseDispatcher {
338             launch {
339                 mutable++
340                 delay(SLOW)
341                 mutable++
342             }
343             assertEquals(0, mutable)
344             runCurrent()
345             assertEquals(1, mutable)
346             advanceTimeBy(SLOW)
347             assertEquals(2, mutable)
348         }
349     }
350 
351     @Test
352     fun pauseDispatcher_withDelay_resumesAfterPause() = runBlockingTest {
353         var mutable = 0
354         assertRunsFast {
355             pauseDispatcher {
356                 delay(1_000)
357                 mutable++
358             }
359         }
360         assertEquals(1, mutable)
361     }
362 
363 
364     @Test
365     fun testWithTestContextThrowingAnAssertionError() {
366         assertFailsWith<TestException> {
367             runBlockingTest {
368                 val expectedError = TestException("hello")
369 
370                 launch {
371                     throw expectedError
372                 }
373 
374                 // don't rethrow or handle the exception
375             }
376         }
377     }
378 
379     @Test
380     fun testExceptionHandlingWithLaunch() {
381         assertFailsWith<TestException> {
382             runBlockingTest {
383                 val expectedError = TestException("hello")
384 
385                 launch {
386                     throw expectedError
387                 }
388             }
389         }
390     }
391 
392     @Test
393     fun testExceptions_notThrownImmediately() {
394         assertFailsWith<TestException> {
395             runBlockingTest {
396                 val expectedException = TestException("hello")
397                 val result = runCatching {
398                     launch {
399                         throw expectedException
400                     }
401                 }
402                 runCurrent()
403                 assertEquals(true, result.isSuccess)
404             }
405         }
406     }
407 
408 
409     private val exceptionHandler = TestCoroutineExceptionHandler()
410 
411     @Test
412     fun testPartialContextOverride() = runBlockingTest(CoroutineName("named")) {
413         assertEquals(CoroutineName("named"), coroutineContext[CoroutineName])
414         assertNotNull(coroutineContext[CoroutineExceptionHandler])
415         assertNotSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler)
416     }
417 
418     @Test
419     fun testPartialDispatcherOverride() {
420         assertFailsWith<IllegalArgumentException> {
421             runBlockingTest(Dispatchers.Unconfined) {
422                 fail("Unreached")
423             }
424         }
425     }
426 
427     @Test
428     fun testOverrideExceptionHandler() = runBlockingTest(exceptionHandler) {
429         assertSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler)
430     }
431 
432     @Test
433     fun testOverrideExceptionHandlerError() {
434         assertFailsWith<IllegalArgumentException> {
435             runBlockingTest(CoroutineExceptionHandler { _, _ -> }) {
436                 fail("Unreached")
437             }
438         }
439     }
440 }