• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
4  */
5 
6 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
7 
8 package kotlinx.coroutines
9 
10 import kotlinx.coroutines.channels.*
11 import kotlin.test.*
12 
13 class WithTimeoutOrNullTest : TestBase() {
14     /**
15      * Tests a case of no timeout and no suspension inside.
16      */
17     @Test
<lambda>null18     fun testBasicNoSuspend() = runTest {
19         expect(1)
20         val result = withTimeoutOrNull(10_000) {
21             expect(2)
22             "OK"
23         }
24         assertEquals("OK", result)
25         finish(3)
26     }
27 
28     /**
29      * Tests a case of no timeout and one suspension inside.
30      */
31     @Test
<lambda>null32     fun testBasicSuspend() = runTest {
33         expect(1)
34         val result = withTimeoutOrNull(10_000) {
35             expect(2)
36             yield()
37             expect(3)
38             "OK"
39         }
40         assertEquals("OK", result)
41         finish(4)
42     }
43 
44     /**
45      * Tests property dispatching of `withTimeoutOrNull` blocks
46      */
47     @Test
<lambda>null48     fun testDispatch() = runTest {
49         expect(1)
50         launch {
51             expect(4)
52             yield() // back to main
53             expect(7)
54         }
55         expect(2)
56         // test that it does not yield to the above job when started
57         val result = withTimeoutOrNull(1000) {
58             expect(3)
59             yield() // yield only now
60             expect(5)
61             "OK"
62         }
63         assertEquals("OK", result)
64         expect(6)
65         yield() // back to launch
66         finish(8)
67     }
68 
69     /**
70      * Tests that a 100% CPU-consuming loop will react on timeout if it has yields.
71      */
72     @Test
<lambda>null73     fun testYieldBlockingWithTimeout() = runTest {
74         expect(1)
75         val result = withTimeoutOrNull(100) {
76             while (true) {
77                 yield()
78             }
79         }
80         assertEquals(null, result)
81         finish(2)
82     }
83 
84     @Test
testSmallTimeoutnull85     fun testSmallTimeout() = runTest {
86         val channel = Channel<Int>(1)
87         val value = withTimeoutOrNull(1) {
88             channel.receive()
89         }
90         assertNull(value)
91     }
92 
93     @Test
<lambda>null94     fun testThrowException() = runTest(expected = {it is AssertionError}) {
<lambda>null95         withTimeoutOrNull(Long.MAX_VALUE) {
96             throw AssertionError()
97         }
98     }
99 
100     @Test
testInnerTimeoutnull101     fun testInnerTimeout() = runTest(
102         expected = { it is CancellationException }
<lambda>null103     ) {
104         withTimeoutOrNull(1000) {
105             withTimeout(10) {
106                 while (true) {
107                     yield()
108                 }
109             }
110             expectUnreached() // will timeout
111         }
112         expectUnreached() // will timeout
113     }
114 
115     @Test
testNestedTimeoutnull116     fun testNestedTimeout() = runTest(expected = { it is TimeoutCancellationException }) {
<lambda>null117         withTimeoutOrNull(Long.MAX_VALUE) {
118             // Exception from this withTimeout is not suppressed by withTimeoutOrNull
119             withTimeout(10) {
120                 delay(Long.MAX_VALUE)
121                 1
122             }
123         }
124 
125         expectUnreached()
126     }
127 
128     @Test
<lambda>null129     fun testOuterTimeout() = runTest {
130         var counter = 0
131         val result = withTimeoutOrNull(250) {
132             while (true) {
133                 val inner = withTimeoutOrNull(100) {
134                     while (true) {
135                         yield()
136                     }
137                 }
138                 assertEquals(null, inner)
139                 counter++
140             }
141         }
142         assertEquals(null, result)
143         check(counter in 1..2) {"Executed: $counter times"}
144     }
145 
146     @Test
<lambda>null147     fun testBadClass() = runTest {
148         val bad = BadClass()
149         val result = withTimeoutOrNull(100) {
150             bad
151         }
152         assertSame(bad, result)
153     }
154 
155     class BadClass {
equalsnull156         override fun equals(other: Any?): Boolean = error("Should not be called")
157         override fun hashCode(): Int = error("Should not be called")
158         override fun toString(): String = error("Should not be called")
159     }
160 
161     @Test
162     fun testNullOnTimeout() = runTest {
163         expect(1)
164         val result = withTimeoutOrNull(100) {
165             expect(2)
166             delay(1000)
167             expectUnreached()
168             "OK"
169         }
170         assertEquals(null, result)
171         finish(3)
172     }
173 
174     @Test
<lambda>null175     fun testSuppressExceptionWithResult() = runTest {
176         expect(1)
177         val result = withTimeoutOrNull(100) {
178             expect(2)
179             try {
180                 delay(1000)
181             } catch (e: CancellationException) {
182                 expect(3)
183             }
184             "OK"
185         }
186         assertEquals(null, result)
187         finish(4)
188     }
189 
190     @Test
<lambda>null191     fun testSuppressExceptionWithAnotherException() = runTest {
192         expect(1)
193         try {
194             withTimeoutOrNull(100) {
195                 expect(2)
196                 try {
197                     delay(1000)
198                 } catch (e: CancellationException) {
199                     expect(3)
200                     throw TestException()
201                 }
202                 expectUnreached()
203                 "OK"
204             }
205             expectUnreached()
206         } catch (e: TestException) {
207             // catches TestException
208             finish(4)
209 
210         }
211     }
212 
213     @Test
<lambda>null214     fun testNegativeTimeout() = runTest {
215         expect(1)
216         var result = withTimeoutOrNull(-1) {
217             expectUnreached()
218         }
219         assertNull(result)
220         result = withTimeoutOrNull(0) {
221             expectUnreached()
222         }
223         assertNull(result)
224         finish(2)
225     }
226 
227     @Test
<lambda>null228     fun testExceptionFromWithinTimeout() = runTest {
229         expect(1)
230         try {
231             expect(2)
232             withTimeoutOrNull(1000) {
233                 expect(3)
234                 throw TestException()
235             }
236             expectUnreached()
237         } catch (e: TestException) {
238             finish(4)
239         }
240     }
241 }
242