Chuck Stein
05/01/2023, 1:39 AMStandardTestDispatcher
limited to one thread? How can I write a test where I need one thread to lock a mutex while another thread waits for the mutex to be unlocked, while the main runTest
block asserts that the mutex is locked in between?ephemient
05/01/2023, 1:50 AMkotlinx.coroutines.sync.Mutex
(or suspended for any other reason), other coroutines can run on the same threadChuck Stein
05/01/2023, 1:51 AMephemient
05/01/2023, 1:52 AMassertTrue(mutex.tryLock())
?Chuck Stein
05/01/2023, 1:57 AMephemient
05/01/2023, 1:59 AM@Test
fun test() = runTest {
val mutex = Mutex()
val job = launch(start = CoroutineStart.UNDISPATCHED) {
mutex.withLock {
delay(100)
}
}
assertFalse(mutex.tryLock())
job.join()
assertTrue(mutex.tryLock())
mutex.unlock()
}
ephemient
05/01/2023, 2:00 AMval job = launch {
mutex.withLock {
delay(100)
}
}
delay(1)
assertFalse(mutex.tryLock())
instead of changing start
ephemient
05/01/2023, 2:01 AMephemient
05/01/2023, 2:08 AMMutex
is locked" if possible?ephemient
05/01/2023, 2:09 AMChuck Stein
05/01/2023, 2:09 AMwithLock
is a non-suspending lambda. (In the production code the lambda would be calling a C++ library that may run some computations that take a while.) So I need to find a way for my test function to hold the mutex in a non-suspending context... would Thread.sleep
be appropriate here? Feels like a code smell still, but I'm not sure of any alternativesephemient
05/01/2023, 2:10 AMephemient
05/01/2023, 2:10 AMephemient
05/01/2023, 2:12 AMwithContext(Dispatchers.Default) {
runInterruptible {
someBlockingJavaCode()
}
}
but whether that'll work in the test may depend on timeouts, I thinkChuck Stein
05/01/2023, 2:13 AMalso consider not testing internal implementation details like "whichThe class I'm testing is essentially wrapping this C++ library to ensure only one thread is calling it at a time. So my goal is to test that guaranteeis locked" if possible?Mutex
Chuck Stein
05/01/2023, 2:16 AMrunInterruptible
beforeephemient
05/01/2023, 2:18 AMprivate val library: Library
private val mutex: Mutex
suspend fun <T> useLibrary(block: (Library) -> T): T = mutex.withLock {
block(library)
}
then that forces all access outside this code to be serialephemient
05/01/2023, 2:18 AMChuck Stein
05/01/2023, 2:19 AMrunInterruptible
circumvent the need to explicitly make computation code cancellable?Chuck Stein
05/01/2023, 2:19 AMthen that forces all access outside this code to be serialthat's essentially what my wrapper is doing
ephemient
05/01/2023, 2:19 AMrunInterruptible
is a bridge between Java thread cancellation and kotlinx.coroutines job cancellationChuck Stein
05/01/2023, 2:19 AMwithTimeout
and analyticsephemient
05/01/2023, 2:19 AMephemient
05/01/2023, 2:20 AMephemient
05/01/2023, 2:21 AMChuck Stein
05/01/2023, 2:21 AM