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