diff --git a/coroutines/src/commonTest/kotlin/SmartRWLockerTests.kt b/coroutines/src/commonTest/kotlin/SmartRWLockerTests.kt index cef0ff93526..75fd251d17b 100644 --- a/coroutines/src/commonTest/kotlin/SmartRWLockerTests.kt +++ b/coroutines/src/commonTest/kotlin/SmartRWLockerTests.kt @@ -1,10 +1,6 @@ -import dev.inmo.micro_utils.coroutines.SmartRWLocker -import dev.inmo.micro_utils.coroutines.withReadAcquire -import dev.inmo.micro_utils.coroutines.withWriteLock -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.delay -import kotlinx.coroutines.joinAll -import kotlinx.coroutines.launch +import dev.inmo.micro_utils.coroutines.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.first import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.test.runTest @@ -57,4 +53,99 @@ class SmartRWLockerTests { assertEquals(expected = readAndWriteWorkers, actual = doneWrites) } } + + @Test + fun simpleWithWriteLockTest() { + val locker = SmartRWLocker() + + runTest { + locker.withWriteLock { + assertEquals(0, locker.readSemaphore.freePermits) + assertEquals(true, locker.writeMutex.isLocked) + } + assertEquals(Int.MAX_VALUE, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + } + } + + @Test + fun failureWithWriteLockTest() { + val locker = SmartRWLocker() + + val exception = IllegalArgumentException() + try { + runTest { + val subscope = kotlinx.coroutines.CoroutineScope(this.coroutineContext) + var happenException: Throwable? = null + try { + locker.withWriteLock { + val checkFunction = fun (): Deferred { + return subscope.async { + assertEquals(0, locker.readSemaphore.freePermits) + assertEquals(true, locker.writeMutex.isLocked) + throw exception + } + } + doInDefault { + assertEquals(0, locker.readSemaphore.freePermits) + assertEquals(true, locker.writeMutex.isLocked) + checkFunction().await() + } + } + } catch (e: Exception) { + happenException = e + } + if (exception != happenException) { + assertEquals(exception, happenException ?.cause) + } + assertEquals(Int.MAX_VALUE, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + } + } catch (e: Exception) { + assertEquals(exception, e) + } + } + + @Test + fun simpleWithReadAcquireTest() { + val locker = SmartRWLocker() + + runTest { + locker.withReadAcquire { + assertEquals(Int.MAX_VALUE - 1, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + locker.withReadAcquire { + assertEquals(Int.MAX_VALUE - 2, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + } + } + assertEquals(Int.MAX_VALUE, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + } + } + + @Test + fun simple2WithWriteLockTest() { + val locker = SmartRWLocker() + + val unlockDelay = 1000L // 1 sec + var unlocked: Boolean = false + runTest { + launch { + locker.withReadAcquire { + delay(unlockDelay) + } + unlocked = true + } + locker.readSemaphore.permitsStateFlow.first { it == Int.MAX_VALUE - 1 } + assertEquals(false, unlocked) + locker.withWriteLock { + assertEquals(true, unlocked) + assertEquals(0, locker.readSemaphore.freePermits) + assertEquals(true, locker.writeMutex.isLocked) + } + assertEquals(Int.MAX_VALUE, locker.readSemaphore.freePermits) + assertEquals(false, locker.writeMutex.isLocked) + } + } }