1 package kotlinx.coroutines 2 3 import kotlinx.coroutines.testing.* 4 import kotlin.test.* 5 6 class AwaitTest : TestBase() { 7 8 @Test <lambda>null9 fun testAwaitAll() = runTest { 10 expect(1) 11 val d = async { 12 expect(3) 13 "OK" 14 } 15 16 val d2 = async { 17 yield() 18 expect(4) 19 1L 20 } 21 22 expect(2) 23 require(d2.isActive && !d2.isCompleted) 24 25 assertEquals(listOf("OK", 1L), awaitAll(d, d2)) 26 expect(5) 27 28 require(d.isCompleted && d2.isCompleted) 29 require(!d.isCancelled && !d2.isCancelled) 30 finish(6) 31 } 32 33 @Test <lambda>null34 fun testAwaitAllLazy() = runTest { 35 expect(1) 36 val d = async(start = CoroutineStart.LAZY) { 37 expect(2) 38 1 39 } 40 val d2 = async(start = CoroutineStart.LAZY) { 41 expect(3) 42 2 43 } 44 assertEquals(listOf(1, 2), awaitAll(d, d2)) 45 finish(4) 46 } 47 48 @Test <lambda>null49 fun testAwaitAllTyped() = runTest { 50 val d1 = async { 1L } 51 val d2 = async { "" } 52 val d3 = async { } 53 54 assertEquals(listOf(1L, ""), listOf(d1, d2).awaitAll()) 55 assertEquals(listOf(1L, Unit), listOf(d1, d3).awaitAll()) 56 assertEquals(listOf("", Unit), listOf(d2, d3).awaitAll()) 57 } 58 59 @Test <lambda>null60 fun testAwaitAllExceptionally() = runTest { 61 expect(1) 62 val d = async { 63 expect(3) 64 "OK" 65 } 66 67 val d2 = async(NonCancellable) { 68 yield() 69 throw TestException() 70 } 71 72 val d3 = async { 73 expect(4) 74 delay(Long.MAX_VALUE) 75 1 76 } 77 78 expect(2) 79 try { 80 awaitAll(d, d2, d3) 81 } catch (e: TestException) { 82 expect(5) 83 } 84 85 yield() 86 require(d.isCompleted && d2.isCancelled && d3.isActive) 87 d3.cancel() 88 finish(6) 89 } 90 91 @Test <lambda>null92 fun testAwaitAllMultipleExceptions() = runTest { 93 val d = async(NonCancellable) { 94 expect(2) 95 throw TestException() 96 } 97 98 val d2 = async(NonCancellable) { 99 yield() 100 throw TestException() 101 } 102 103 val d3 = async { 104 yield() 105 } 106 107 expect(1) 108 try { 109 awaitAll(d, d2, d3) 110 } catch (e: TestException) { 111 expect(3) 112 } 113 114 finish(4) 115 } 116 117 @Test <lambda>null118 fun testAwaitAllCancellation() = runTest { 119 val outer = async { 120 121 expect(1) 122 val inner = async { 123 expect(4) 124 delay(Long.MAX_VALUE) 125 } 126 127 expect(2) 128 awaitAll(inner) 129 expectUnreached() 130 } 131 132 yield() 133 expect(3) 134 yield() 135 require(outer.isActive) 136 outer.cancel() 137 require(outer.isCancelled) 138 finish(5) 139 } 140 141 @Test <lambda>null142 fun testAwaitAllPartiallyCompleted() = runTest { 143 val d1 = async { expect(1); 1 } 144 d1.await() 145 val d2 = async { expect(3); 2 } 146 expect(2) 147 assertEquals(listOf(1, 2), awaitAll(d1, d2)) 148 require(d1.isCompleted && d2.isCompleted) 149 finish(4) 150 } 151 152 @Test <lambda>null153 fun testAwaitAllPartiallyCompletedExceptionally() = runTest { 154 val d1 = async(NonCancellable) { 155 expect(1) 156 throw TestException() 157 } 158 159 yield() 160 161 // This job is called after exception propagation 162 val d2 = async { expect(4) } 163 164 expect(2) 165 try { 166 awaitAll(d1, d2) 167 expectUnreached() 168 } catch (e: TestException) { 169 expect(3) 170 } 171 172 require(d2.isActive) 173 d2.await() 174 require(d1.isCompleted && d2.isCompleted) 175 finish(5) 176 } 177 178 @Test <lambda>null179 fun testAwaitAllFullyCompleted() = runTest { 180 val d1 = CompletableDeferred(Unit) 181 val d2 = CompletableDeferred(Unit) 182 val job = async { expect(3) } 183 expect(1) 184 awaitAll(d1, d2) 185 expect(2) 186 job.await() 187 finish(4) 188 } 189 190 @Test <lambda>null191 fun testAwaitOnSet() = runTest { 192 val d1 = CompletableDeferred(Unit) 193 val d2 = CompletableDeferred(Unit) 194 val job = async { expect(2) } 195 expect(1) 196 listOf(d1, d2, job).awaitAll() 197 finish(3) 198 } 199 200 @Test <lambda>null201 fun testAwaitAllFullyCompletedExceptionally() = runTest { 202 val d1 = CompletableDeferred<Unit>(parent = null) 203 .apply { completeExceptionally(TestException()) } 204 val d2 = CompletableDeferred<Unit>(parent = null) 205 .apply { completeExceptionally(TestException()) } 206 val job = async { expect(3) } 207 expect(1) 208 try { 209 awaitAll(d1, d2) 210 } catch (e: TestException) { 211 expect(2) 212 } 213 214 job.await() 215 finish(4) 216 } 217 218 @Test <lambda>null219 fun testAwaitAllSameJobMultipleTimes() = runTest { 220 val d = async { "OK" } 221 // Duplicates are allowed though kdoc doesn't guarantee that 222 assertEquals(listOf("OK", "OK", "OK"), awaitAll(d, d, d)) 223 } 224 225 @Test <lambda>null226 fun testAwaitAllSameThrowingJobMultipleTimes() = runTest { 227 val d1 = 228 async(NonCancellable) { throw TestException() } 229 val d2 = async { } // do nothing 230 231 try { 232 expect(1) 233 // Duplicates are allowed though kdoc doesn't guarantee that 234 awaitAll(d1, d2, d1, d2) 235 expectUnreached() 236 } catch (e: TestException) { 237 finish(2) 238 } 239 } 240 241 @Test <lambda>null242 fun testAwaitAllEmpty() = runTest { 243 expect(1) 244 assertEquals(emptyList(), awaitAll<Unit>()) 245 assertEquals(emptyList(), emptyList<Deferred<Unit>>().awaitAll()) 246 finish(2) 247 } 248 249 // joinAll 250 251 @Test <lambda>null252 fun testJoinAll() = runTest { 253 val d1 = launch { expect(2) } 254 val d2 = async { 255 expect(3) 256 "OK" 257 } 258 val d3 = launch { expect(4) } 259 260 expect(1) 261 joinAll(d1, d2, d3) 262 finish(5) 263 } 264 265 @Test <lambda>null266 fun testJoinAllLazy() = runTest { 267 expect(1) 268 val d = async(start = CoroutineStart.LAZY) { 269 expect(2) 270 } 271 val d2 = launch(start = CoroutineStart.LAZY) { 272 expect(3) 273 } 274 joinAll(d, d2) 275 finish(4) 276 } 277 278 @Test <lambda>null279 fun testJoinAllExceptionally() = runTest { 280 val d1 = launch { 281 expect(2) 282 } 283 val d2 = async(NonCancellable) { 284 expect(3) 285 throw TestException() 286 } 287 val d3 = async { 288 expect(4) 289 } 290 291 expect(1) 292 joinAll(d1, d2, d3) 293 finish(5) 294 } 295 296 @Test <lambda>null297 fun testJoinAllCancellation() = runTest { 298 val outer = launch { 299 expect(2) 300 val inner = launch { 301 expect(3) 302 delay(Long.MAX_VALUE) 303 } 304 305 joinAll(inner) 306 expectUnreached() 307 } 308 309 expect(1) 310 yield() 311 require(outer.isActive) 312 yield() 313 outer.cancel() 314 outer.join() 315 finish(4) 316 } 317 318 @Test <lambda>null319 fun testJoinAllAlreadyCompleted() = runTest { 320 val job = launch { 321 expect(1) 322 } 323 324 job.join() 325 expect(2) 326 327 joinAll(job) 328 finish(3) 329 } 330 331 @Test <lambda>null332 fun testJoinAllEmpty() = runTest { 333 expect(1) 334 joinAll() 335 listOf<Job>().joinAll() 336 finish(2) 337 } 338 339 @Test <lambda>null340 fun testJoinAllSameJob() = runTest { 341 val job = launch { } 342 joinAll(job, job, job) 343 } 344 345 @Test <lambda>null346 fun testJoinAllSameJobExceptionally() = runTest { 347 val job = 348 async(NonCancellable) { throw TestException() } 349 joinAll(job, job, job) 350 } 351 352 @Test testAwaitAllDelegatesnull353 fun testAwaitAllDelegates() = runTest { 354 expect(1) 355 val deferred = CompletableDeferred<String>() 356 @OptIn(InternalForInheritanceCoroutinesApi::class) 357 val delegate = object : Deferred<String> by deferred {} 358 launch { 359 expect(3) 360 deferred.complete("OK") 361 } 362 expect(2) 363 awaitAll(delegate) 364 finish(4) 365 } 366 367 @Test testCancelAwaitAllDelegatenull368 fun testCancelAwaitAllDelegate() = runTest { 369 expect(1) 370 val deferred = CompletableDeferred<String>() 371 @OptIn(InternalForInheritanceCoroutinesApi::class) 372 val delegate = object : Deferred<String> by deferred {} 373 launch { 374 expect(3) 375 deferred.cancel() 376 } 377 expect(2) 378 assertFailsWith<CancellationException> { awaitAll(delegate) } 379 finish(4) 380 } 381 } 382