blob: f1ef142b4ac2e8977bed708be8e4866c78aa533d [file] [log] [blame]
Roman Elizarova7db8ec2017-12-21 22:45:12 +03001/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03002 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarova7db8ec2017-12-21 22:45:12 +03003 */
4
Roman Elizarov9d5abcd2017-12-21 16:54:30 +03005package kotlinx.coroutines.experimental
6
Roman Elizarov9fe5f462018-02-21 19:05:52 +03007import kotlin.coroutines.experimental.*
Roman Elizarov9d5abcd2017-12-21 16:54:30 +03008import kotlin.test.*
9
Roman Elizarovaa461cf2018-04-11 13:20:29 +030010class JobTest : TestBase() {
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030011 @Test
12 fun testState() {
13 val job = Job()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030014 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030015 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030016 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030017 }
18
19 @Test
20 fun testHandler() {
21 val job = Job()
22 var fireCount = 0
23 job.invokeOnCompletion { fireCount++ }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030024 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030025 assertEquals(0, fireCount)
26 // cancel once
27 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030028 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030029 assertEquals(1, fireCount)
30 // cancel again
31 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030032 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030033 assertEquals(1, fireCount)
34 }
35
36 @Test
37 fun testManyHandlers() {
38 val job = Job()
39 val n = 100 * stressTestMultiplier
40 val fireCount = IntArray(n)
41 for (i in 0 until n) job.invokeOnCompletion { fireCount[i]++ }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030042 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030043 for (i in 0 until n) assertEquals(0, fireCount[i])
44 // cancel once
45 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030046 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030047 for (i in 0 until n) assertEquals(1, fireCount[i])
48 // cancel again
49 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030050 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030051 for (i in 0 until n) assertEquals(1, fireCount[i])
52 }
53
54 @Test
55 fun testUnregisterInHandler() {
56 val job = Job()
57 val n = 100 * stressTestMultiplier
58 val fireCount = IntArray(n)
59 for (i in 0 until n) {
60 var registration: DisposableHandle? = null
61 registration = job.invokeOnCompletion {
62 fireCount[i]++
63 registration!!.dispose()
64 }
65 }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030066 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030067 for (i in 0 until n) assertEquals(0, fireCount[i])
68 // cancel once
69 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030070 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030071 for (i in 0 until n) assertEquals(1, fireCount[i])
72 // cancel again
73 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030074 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030075 for (i in 0 until n) assertEquals(1, fireCount[i])
76 }
77
78 @Test
79 fun testManyHandlersWithUnregister() {
80 val job = Job()
81 val n = 100 * stressTestMultiplier
82 val fireCount = IntArray(n)
83 val registrations = Array<DisposableHandle>(n) { i -> job.invokeOnCompletion { fireCount[i]++ } }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030084 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030085 fun unreg(i: Int) = i % 4 <= 1
86 for (i in 0 until n) if (unreg(i)) registrations[i].dispose()
87 for (i in 0 until n) assertEquals(0, fireCount[i])
88 job.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030089 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +030090 for (i in 0 until n) assertEquals(if (unreg(i)) 0 else 1, fireCount[i])
91 }
92
93 @Test
94 fun testExceptionsInHandler() {
95 val job = Job()
96 val n = 100 * stressTestMultiplier
97 val fireCount = IntArray(n)
98 class TestException : Throwable()
99 for (i in 0 until n) job.invokeOnCompletion {
100 fireCount[i]++
101 throw TestException()
102 }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300103 assertTrue(job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300104 for (i in 0 until n) assertEquals(0, fireCount[i])
105 val tryCancel = Try<Unit> { job.cancel() }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300106 assertTrue(!job.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300107 for (i in 0 until n) assertEquals(1, fireCount[i])
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300108 assertTrue(tryCancel.exception is CompletionHandlerException)
109 assertTrue(tryCancel.exception!!.cause is TestException)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300110 }
111
112 @Test
113 fun testCancelledParent() {
114 val parent = Job()
115 parent.cancel()
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300116 assertTrue(!parent.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300117 val child = Job(parent)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300118 assertTrue(!child.isActive)
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300119 }
120
121 @Test
122 fun testDisposeSingleHandler() {
123 val job = Job()
124 var fireCount = 0
125 val handler = job.invokeOnCompletion { fireCount++ }
126 handler.dispose()
127 job.cancel()
128 assertEquals(0, fireCount)
129 }
130
131 @Test
132 fun testDisposeMultipleHandler() {
133 val job = Job()
134 val handlerCount = 10
135 var fireCount = 0
136 val handlers = Array(handlerCount) { job.invokeOnCompletion { fireCount++ } }
137 handlers.forEach { it.dispose() }
138 job.cancel()
139 assertEquals(0, fireCount)
140 }
Roman Elizarov4d626de2018-01-11 22:57:28 +0300141
142 @Test
143 fun testCancelAndJoinParentWaitChildren() = runTest {
144 expect(1)
145 val parent = Job()
146 launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) {
147 expect(2)
148 try {
149 yield() // will get cancelled
150 } finally {
151 expect(5)
152 }
153 }
154 expect(3)
155 parent.cancel()
156 expect(4)
157 parent.join()
158 finish(6)
159 }
Roman Elizarov9d5abcd2017-12-21 16:54:30 +0300160}