1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
import kotlin.test.*
class AtomicCancellationTest : TestBase() {
@Test
fun testSendAtomicCancel() = runBlocking {
expect(1)
val channel = Channel<Int>()
val job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
channel.send(42) // suspends
expect(4) // should execute despite cancellation
}
expect(3)
assertEquals(42, channel.receive()) // will schedule sender for further execution
job.cancel() // cancel the job next
yield() // now yield
finish(5)
}
@Test
fun testSelectSendAtomicCancel() = runBlocking {
expect(1)
val channel = Channel<Int>()
val job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
val result = select<String> { // suspends
channel.onSend(42) {
expect(4)
"OK"
}
}
assertEquals("OK", result)
expect(5) // should execute despite cancellation
}
expect(3)
assertEquals(42, channel.receive()) // will schedule sender for further execution
job.cancel() // cancel the job next
yield() // now yield
finish(6)
}
@Test
fun testReceiveAtomicCancel() = runBlocking {
expect(1)
val channel = Channel<Int>()
val job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
assertEquals(42, channel.receive()) // suspends
expect(4) // should execute despite cancellation
}
expect(3)
channel.send(42) // will schedule receiver for further execution
job.cancel() // cancel the job next
yield() // now yield
finish(5)
}
@Test
fun testSelectReceiveAtomicCancel() = runBlocking {
expect(1)
val channel = Channel<Int>()
val job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
val result = select<String> { // suspends
channel.onReceive {
assertEquals(42, it)
expect(4)
"OK"
}
}
assertEquals("OK", result)
expect(5) // should execute despite cancellation
}
expect(3)
channel.send(42) // will schedule receiver for further execution
job.cancel() // cancel the job next
yield() // now yield
finish(6)
}
@Test
fun testSelectDeferredAwaitCancellable() = runBlocking {
expect(1)
val deferred = async { // deferred, not yet complete
expect(4)
"OK"
}
assertEquals(false, deferred.isCompleted)
var job: Job? = null
launch { // will cancel job as soon as deferred completes
expect(5)
assertEquals(true, deferred.isCompleted)
job!!.cancel()
}
job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
try {
select<Unit> { // suspends
deferred.onAwait { expectUnreached() }
}
expectUnreached() // will not execute -- cancelled while dispatched
} finally {
finish(7) // but will execute finally blocks
}
}
expect(3) // continues to execute when job suspends
yield() // to deferred & canceller
expect(6)
}
@Test
fun testSelectJobJoinCancellable() = runBlocking {
expect(1)
val jobToJoin = launch { // not yet complete
expect(4)
}
assertEquals(false, jobToJoin.isCompleted)
var job: Job? = null
launch { // will cancel job as soon as jobToJoin completes
expect(5)
assertEquals(true, jobToJoin.isCompleted)
job!!.cancel()
}
job = launch(start = CoroutineStart.UNDISPATCHED) {
expect(2)
try {
select<Unit> { // suspends
jobToJoin.onJoin { expectUnreached() }
}
expectUnreached() // will not execute -- cancelled while dispatched
} finally {
finish(7) // but will execute finally blocks
}
}
expect(3) // continues to execute when job suspends
yield() // to jobToJoin & canceller
expect(6)
}
}
|