blob: 050a103a86610dcc9646733be59c2fe9031b50eb [file] [log] [blame]
Roman Elizarov8bd52542017-02-14 15:51:58 +03001/*
2 * Copyright 2016-2017 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Roman Elizarovf8fc4782017-02-22 10:35:08 +030017package kotlinx.coroutines.experimental.sync
Roman Elizarov8bd52542017-02-14 15:51:58 +030018
Roman Elizarovf8fc4782017-02-22 10:35:08 +030019import kotlinx.coroutines.experimental.*
Roman Elizarovaa461cf2018-04-11 13:20:29 +030020import kotlin.test.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030021import kotlin.coroutines.experimental.*
Roman Elizarov8bd52542017-02-14 15:51:58 +030022
23class MutexTest : TestBase() {
24 @Test
Roman Elizarovaa461cf2018-04-11 13:20:29 +030025 fun testSimple() = runTest {
Roman Elizarov8bd52542017-02-14 15:51:58 +030026 val mutex = Mutex()
27 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030028 launch(coroutineContext) {
Roman Elizarov8bd52542017-02-14 15:51:58 +030029 expect(4)
30 mutex.lock() // suspends
31 expect(7) // now got lock
32 mutex.unlock()
33 expect(8)
34 }
35 expect(2)
36 mutex.lock() // locked
37 expect(3)
38 yield() // yield to child
39 expect(5)
40 mutex.unlock()
41 expect(6)
42 yield() // now child has lock
43 finish(9)
44 }
45
46 @Test
47 fun tryLockTest() {
48 val mutex = Mutex()
Roman Elizarov33ecdca2017-02-15 10:53:56 +030049 assertFalse(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030050 assertTrue(mutex.tryLock())
Roman Elizarov33ecdca2017-02-15 10:53:56 +030051 assertTrue(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030052 assertFalse(mutex.tryLock())
Roman Elizarov33ecdca2017-02-15 10:53:56 +030053 assertTrue(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030054 mutex.unlock()
Roman Elizarov33ecdca2017-02-15 10:53:56 +030055 assertFalse(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030056 assertTrue(mutex.tryLock())
Roman Elizarov33ecdca2017-02-15 10:53:56 +030057 assertTrue(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030058 assertFalse(mutex.tryLock())
Roman Elizarov33ecdca2017-02-15 10:53:56 +030059 assertTrue(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030060 mutex.unlock()
Roman Elizarov33ecdca2017-02-15 10:53:56 +030061 assertFalse(mutex.isLocked)
Roman Elizarov8bd52542017-02-14 15:51:58 +030062 }
63
64 @Test
Roman Elizarovaa461cf2018-04-11 13:20:29 +030065 fun withLockTest() = runTest {
Roman Elizarovc02ee112017-04-19 12:57:38 +030066 val mutex = Mutex()
67 assertFalse(mutex.isLocked)
68 mutex.withLock {
69 assertTrue(mutex.isLocked)
70 }
71 assertFalse(mutex.isLocked)
72 }
73
74 @Test
Roman Elizarov11c140a2017-07-21 21:12:55 +030075 fun testUnconfinedStackOverflow() {
76 val waiters = 10000
77 val mutex = Mutex(true)
78 var done = 0
79 repeat(waiters) {
80 launch(Unconfined) { // a lot of unconfined waiters
81 mutex.withLock {
82 done++
83 }
84 }
85 }
86 mutex.unlock() // should not produce StackOverflowError
Roman Elizarovaa461cf2018-04-11 13:20:29 +030087 assertEquals(waiters, done)
Roman Elizarov11c140a2017-07-21 21:12:55 +030088 }
Francesco Vasco14328d12017-07-26 15:31:15 +020089
90 @Test
Roman Elizarovaa461cf2018-04-11 13:20:29 +030091 fun holdLock() = runTest {
Francesco Vasco14328d12017-07-26 15:31:15 +020092 val mutex = Mutex()
93 val firstOwner = Any()
94 val secondOwner = Any()
95
96 // no lock
97 assertFalse(mutex.holdsLock(firstOwner))
98 assertFalse(mutex.holdsLock(secondOwner))
99
100 // owner firstOwner
101 mutex.lock(firstOwner)
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300102 val secondLockJob = launch {
Francesco Vasco14328d12017-07-26 15:31:15 +0200103 mutex.lock(secondOwner)
104 }
105
106 assertTrue(mutex.holdsLock(firstOwner))
107 assertFalse(mutex.holdsLock(secondOwner))
108
109 // owner secondOwner
110 mutex.unlock(firstOwner)
111 secondLockJob.join()
112
113 assertFalse(mutex.holdsLock(firstOwner))
114 assertTrue(mutex.holdsLock(secondOwner))
115
116 mutex.unlock(secondOwner)
117
118 // no lock
119 assertFalse(mutex.holdsLock(firstOwner))
120 assertFalse(mutex.holdsLock(secondOwner))
121 }
Roman Elizarov8bd52542017-02-14 15:51:58 +0300122}