• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "UNREACHABLE_CODE") // KT-21913
2 
3 package kotlinx.coroutines
4 
5 import kotlinx.coroutines.testing.*
6 import kotlin.test.*
7 import kotlin.time.*
8 import kotlin.time.Duration.Companion.milliseconds
9 import kotlin.time.Duration.Companion.seconds
10 
11 class WithTimeoutDurationTest : TestBase() {
12     /**
13      * Tests a case of no timeout and no suspension inside.
14      */
15     @Test
<lambda>null16     fun testBasicNoSuspend() = runTest {
17         expect(1)
18         val result = withTimeout(10.seconds) {
19             expect(2)
20             "OK"
21         }
22         assertEquals("OK", result)
23         finish(3)
24     }
25 
26     /**
27      * Tests a case of no timeout and one suspension inside.
28      */
29     @Test
<lambda>null30     fun testBasicSuspend() = runTest {
31         expect(1)
32         val result = withTimeout(10.seconds) {
33             expect(2)
34             yield()
35             expect(3)
36             "OK"
37         }
38         assertEquals("OK", result)
39         finish(4)
40     }
41 
42     /**
43      * Tests proper dispatching of `withTimeout` blocks
44      */
45     @Test
<lambda>null46     fun testDispatch() = runTest {
47         expect(1)
48         launch {
49             expect(4)
50             yield() // back to main
51             expect(7)
52         }
53         expect(2)
54         // test that it does not yield to the above job when started
55         val result = withTimeout(1.seconds) {
56             expect(3)
57             yield() // yield only now
58             expect(5)
59             "OK"
60         }
61         assertEquals("OK", result)
62         expect(6)
63         yield() // back to launch
64         finish(8)
65     }
66 
67 
68     /**
69      * Tests that a 100% CPU-consuming loop will react on timeout if it has yields.
70      */
71     @Test
testYieldBlockingWithTimeoutnull72     fun testYieldBlockingWithTimeout() = runTest(
73             expected = { it is CancellationException }
<lambda>null74     ) {
75         withTimeout(100.milliseconds) {
76             while (true) {
77                 yield()
78             }
79         }
80     }
81 
82     /**
83      * Tests that [withTimeout] waits for children coroutines to complete.
84      */
85     @Test
<lambda>null86     fun testWithTimeoutChildWait() = runTest {
87         expect(1)
88         withTimeout(100.milliseconds) {
89             expect(2)
90             // launch child with timeout
91             launch {
92                 expect(4)
93             }
94             expect(3)
95             // now will wait for child before returning
96         }
97         finish(5)
98     }
99 
100     @Test
<lambda>null101     fun testBadClass() = runTest {
102         val bad = BadClass()
103         val result = withTimeout(100.milliseconds) {
104             bad
105         }
106         assertSame(bad, result)
107     }
108 
109     class BadClass {
equalsnull110         override fun equals(other: Any?): Boolean = error("Should not be called")
111         override fun hashCode(): Int = error("Should not be called")
112         override fun toString(): String = error("Should not be called")
113     }
114 
115     @Test
116     fun testExceptionOnTimeout() = runTest {
117         expect(1)
118         try {
119             withTimeout(100.milliseconds) {
120                 expect(2)
121                 delay(1000.milliseconds)
122                 expectUnreached()
123                 "OK"
124             }
125         } catch (e: CancellationException) {
126             assertEquals("Timed out waiting for 100 ms", e.message)
127             finish(3)
128         }
129     }
130 
131     @Test
testSuppressExceptionWithResultnull132     fun testSuppressExceptionWithResult() = runTest(
133             expected = { it is CancellationException }
<lambda>null134     ) {
135         expect(1)
136         withTimeout(100.milliseconds) {
137             expect(2)
138             try {
139                 delay(1000.milliseconds)
140             } catch (e: CancellationException) {
141                 finish(3)
142             }
143             "OK"
144         }
145         expectUnreached()
146     }
147 
148     @Test
<lambda>null149     fun testSuppressExceptionWithAnotherException() = runTest {
150         expect(1)
151         try {
152             withTimeout(100.milliseconds) {
153                 expect(2)
154                 try {
155                     delay(1000.milliseconds)
156                 } catch (e: CancellationException) {
157                     expect(3)
158                     throw TestException()
159                 }
160                 expectUnreached()
161                 "OK"
162             }
163             expectUnreached()
164         } catch (e: TestException) {
165             finish(4)
166         }
167     }
168 
169     @Test
<lambda>null170     fun testNegativeTimeout() = runTest {
171         expect(1)
172         try {
173             withTimeout(-1.milliseconds) {
174                 expectUnreached()
175                 "OK"
176             }
177         } catch (e: TimeoutCancellationException) {
178             assertEquals("Timed out immediately", e.message)
179             finish(2)
180         }
181     }
182 
183     @Test
<lambda>null184     fun testExceptionFromWithinTimeout() = runTest {
185         expect(1)
186         try {
187             expect(2)
188             withTimeout(1.seconds) {
189                 expect(3)
190                 throw TestException()
191             }
192             expectUnreached()
193         } catch (e: TestException) {
194             finish(4)
195         }
196     }
197 
198     @Test
<lambda>null199     fun testIncompleteWithTimeoutState() = runTest {
200         lateinit var timeoutJob: Job
201         val handle = withTimeout(Duration.INFINITE) {
202             timeoutJob = coroutineContext[Job]!!
203             timeoutJob.invokeOnCompletion { }
204         }
205 
206         handle.dispose()
207         timeoutJob.join()
208         assertTrue(timeoutJob.isCompleted)
209         assertFalse(timeoutJob.isActive)
210         assertFalse(timeoutJob.isCancelled)
211     }
212 }
213