Use cooperative coroutine cancellation in test code

Our test code relies on `withTimeout*` and `while(true)`
in a few places to wait for things to happen. However,
having a timeout is not enough: if the coroutine is busy,
even if the timeout elapses, the work will not be interrupted.
That's because cancellation in Kotlin coroutines is cooperative,
see [the docs](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/cancellation-and-timeouts.md#cancellation-is-cooperative)
for more details.

This commit uses cooperative cancellation so that tests will
break, instead of hanging forever.
This commit is contained in:
Alessio Placitelli 2020-02-12 12:18:51 +01:00
Родитель 019c96cd0e
Коммит f9b20a7530
3 изменённых файлов: 7 добавлений и 4 удалений

Просмотреть файл

@ -8,6 +8,7 @@ import android.content.Context
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.testing.WorkManagerTestInitHelper
import kotlinx.coroutines.isActive
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
@ -35,7 +36,7 @@ internal fun testFlushWorkManagerJob(context: Context, workTag: String, timeoutM
return@withTimeout
}
}
} while (true)
} while (isActive)
}
}
}

Просмотреть файл

@ -9,6 +9,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Dispatchers as KotlinDispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@ -107,7 +108,7 @@ class DispatchersTest {
// Wait for the flushed tasks to be executed.
runBlocking {
withTimeoutOrNull(2000) {
while (threadCanary.get() != 3 || Dispatchers.API.taskQueue.size > 0) {
while (isActive && (threadCanary.get() != 3 || Dispatchers.API.taskQueue.size > 0)) {
delay(1)
}
} ?: assertTrue("Timed out waiting for tasks to execute", false)
@ -157,7 +158,7 @@ class DispatchersTest {
runBlocking {
// Ensure that all the required jobs have been added to the list.
withTimeoutOrNull(2000) {
while (counter.get() < 100) {
while (isActive && counter.get() < 100) {
delay(1)
}
} ?: assertEquals("Timed out waiting for tasks to execute", 100, counter.get())

Просмотреть файл

@ -13,6 +13,7 @@ import androidx.test.core.app.ApplicationProvider
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.testing.WorkManagerTestInitHelper
import kotlinx.coroutines.isActive
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import org.json.JSONObject
@ -197,7 +198,7 @@ internal fun waitForEnqueuedWorker(
if (getWorkerStatus(context, workTag).isEnqueued) {
return@withTimeout
}
} while (true)
} while (isActive)
}
}