91 lines
2.6 KiB
Kotlin
91 lines
2.6 KiB
Kotlin
package cash.z.ecc.android.sdk.darkside.test
|
|
|
|
import android.content.Context
|
|
import androidx.test.platform.app.InstrumentationRegistry
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.cancel
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.newFixedThreadPoolContext
|
|
import kotlinx.coroutines.runBlocking
|
|
import org.junit.After
|
|
import org.junit.AfterClass
|
|
import org.junit.Before
|
|
import org.junit.BeforeClass
|
|
import java.util.concurrent.TimeoutException
|
|
|
|
@OptIn(DelicateCoroutinesApi::class)
|
|
open class ScopedTest(val defaultTimeout: Long = 2000L) : DarksideTestPrerequisites() {
|
|
protected lateinit var testScope: CoroutineScope
|
|
|
|
// if an androidTest doesn't need a context, then maybe it should be a unit test instead?!
|
|
val context: Context = InstrumentationRegistry.getInstrumentation().context
|
|
|
|
@Before
|
|
fun start() {
|
|
testScope =
|
|
CoroutineScope(
|
|
Job(classScope.coroutineContext[Job]!!) +
|
|
newFixedThreadPoolContext(
|
|
5,
|
|
this.javaClass.simpleName
|
|
)
|
|
)
|
|
}
|
|
|
|
@After
|
|
fun end() =
|
|
runBlocking<Unit> {
|
|
testScope.cancel()
|
|
testScope.coroutineContext[Job]?.join()
|
|
}
|
|
|
|
fun timeout(
|
|
duration: Long,
|
|
block: suspend () -> Unit
|
|
) = timeoutWith(testScope, duration, block)
|
|
|
|
companion object {
|
|
@JvmStatic
|
|
lateinit var classScope: CoroutineScope
|
|
|
|
@BeforeClass
|
|
@JvmStatic
|
|
fun createScope() {
|
|
classScope =
|
|
CoroutineScope(
|
|
SupervisorJob() + newFixedThreadPoolContext(2, this::class.java.simpleName)
|
|
)
|
|
}
|
|
|
|
@AfterClass
|
|
@JvmStatic
|
|
fun destroyScope() =
|
|
runBlocking<Unit> {
|
|
classScope.cancel()
|
|
classScope.coroutineContext[Job]?.join()
|
|
}
|
|
|
|
@JvmStatic
|
|
fun timeoutWith(
|
|
scope: CoroutineScope,
|
|
duration: Long,
|
|
block: suspend () -> Unit
|
|
) {
|
|
scope.launch {
|
|
delay(duration)
|
|
val message = "ERROR: Test timed out after ${duration}ms"
|
|
throw TimeoutException(message)
|
|
}.let { selfDestruction ->
|
|
scope.launch {
|
|
block()
|
|
selfDestruction.cancel()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|