зеркало из https://github.com/mozilla/glean.git
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:
Родитель
019c96cd0e
Коммит
f9b20a7530
|
@ -8,6 +8,7 @@ import android.content.Context
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.testing.WorkManagerTestInitHelper
|
import androidx.work.testing.WorkManagerTestInitHelper
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ internal fun testFlushWorkManagerJob(context: Context, workTag: String, timeoutM
|
||||||
return@withTimeout
|
return@withTimeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (true)
|
} while (isActive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Dispatchers as KotlinDispatchers
|
import kotlinx.coroutines.Dispatchers as KotlinDispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.joinAll
|
import kotlinx.coroutines.joinAll
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
@ -107,7 +108,7 @@ class DispatchersTest {
|
||||||
// Wait for the flushed tasks to be executed.
|
// Wait for the flushed tasks to be executed.
|
||||||
runBlocking {
|
runBlocking {
|
||||||
withTimeoutOrNull(2000) {
|
withTimeoutOrNull(2000) {
|
||||||
while (threadCanary.get() != 3 || Dispatchers.API.taskQueue.size > 0) {
|
while (isActive && (threadCanary.get() != 3 || Dispatchers.API.taskQueue.size > 0)) {
|
||||||
delay(1)
|
delay(1)
|
||||||
}
|
}
|
||||||
} ?: assertTrue("Timed out waiting for tasks to execute", false)
|
} ?: assertTrue("Timed out waiting for tasks to execute", false)
|
||||||
|
@ -157,7 +158,7 @@ class DispatchersTest {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
// Ensure that all the required jobs have been added to the list.
|
// Ensure that all the required jobs have been added to the list.
|
||||||
withTimeoutOrNull(2000) {
|
withTimeoutOrNull(2000) {
|
||||||
while (counter.get() < 100) {
|
while (isActive && counter.get() < 100) {
|
||||||
delay(1)
|
delay(1)
|
||||||
}
|
}
|
||||||
} ?: assertEquals("Timed out waiting for tasks to execute", 100, counter.get())
|
} ?: 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.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.testing.WorkManagerTestInitHelper
|
import androidx.work.testing.WorkManagerTestInitHelper
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
@ -197,7 +198,7 @@ internal fun waitForEnqueuedWorker(
|
||||||
if (getWorkerStatus(context, workTag).isEnqueued) {
|
if (getWorkerStatus(context, workTag).isEnqueued) {
|
||||||
return@withTimeout
|
return@withTimeout
|
||||||
}
|
}
|
||||||
} while (true)
|
} while (isActive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче