1 /* 2 * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines 6 7 import org.junit.rules.* 8 import org.junit.runner.* 9 import org.junit.runners.model.* 10 import java.util.concurrent.* 11 import kotlin.coroutines.* 12 13 class ExecutorRule(private val numberOfThreads: Int) : TestRule, ExecutorCoroutineDispatcher() { 14 15 private var _executor: ExecutorCoroutineDispatcher? = null 16 override val executor: Executor 17 get() = _executor?.executor ?: error("Executor is not initialized") 18 applynull19 override fun apply(base: Statement, description: Description): Statement { 20 return object : Statement() { 21 override fun evaluate() { 22 val threadPrefix = description.className.substringAfterLast(".") + "#" + description.methodName 23 _executor = newFixedThreadPoolContext(numberOfThreads, threadPrefix) 24 ignoreLostThreads(threadPrefix) 25 try { 26 return base.evaluate() 27 } finally { 28 val service = executor as ExecutorService 29 service.shutdown() 30 if (!service.awaitTermination(10, TimeUnit.SECONDS)) { 31 error("Test $description timed out") 32 } 33 } 34 } 35 } 36 } 37 dispatchnull38 override fun dispatch(context: CoroutineContext, block: Runnable) { 39 _executor?.dispatch(context, block) ?: error("Executor is not initialized") 40 } 41 closenull42 override fun close() { 43 error("Cannot be closed manually") 44 } 45 } 46