Skip to content

Commit d0774bc

Browse files
committed
Add uncaught exception handler in TestBase.before and validate that no uncaught exceptions are present in TestBase.after
1 parent e3ab2a6 commit d0774bc

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

core/kotlinx-coroutines-core/test/TestBase.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ package kotlinx.coroutines
77
import kotlinx.coroutines.internal.*
88
import kotlinx.coroutines.scheduling.*
99
import org.junit.*
10+
import java.util.*
1011
import java.util.concurrent.atomic.*
12+
import kotlin.test.*
1113

1214
private val VERBOSE = systemProp("test.verbose", false)
1315

@@ -48,6 +50,12 @@ public actual open class TestBase actual constructor() {
4850
private var finished = AtomicBoolean()
4951
private var error = AtomicReference<Throwable>()
5052

53+
// Shutdown sequence
54+
private lateinit var threadsBefore: Set<Thread>
55+
private val uncaughtExceptions = Collections.synchronizedList(ArrayList<Throwable>())
56+
private var originalUncaughtExceptionHandler: Thread.UncaughtExceptionHandler? = null
57+
private val SHUTDOWN_TIMEOUT = 10_000L // 10s at most to wait
58+
5159
/**
5260
* Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not
5361
* complete successfully even if this exception is consumed somewhere in the test.
@@ -105,13 +113,12 @@ public actual open class TestBase actual constructor() {
105113
finished.set(false)
106114
}
107115

108-
private lateinit var threadsBefore: Set<Thread>
109-
private val SHUTDOWN_TIMEOUT = 10_000L // 10s at most to wait
110-
111116
@Before
112117
fun before() {
113118
initPoolsBeforeTest()
114119
threadsBefore = currentThreads()
120+
originalUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
121+
Thread.setDefaultUncaughtExceptionHandler({ t, e -> uncaughtExceptions.add(e) })
115122
}
116123

117124
@After
@@ -120,6 +127,8 @@ public actual open class TestBase actual constructor() {
120127
check(actionIndex.get() == 0 || finished.get()) { "Expecting that 'finish(...)' was invoked, but it was not" }
121128
shutdownPoolsAfterTest()
122129
checkTestThreads(threadsBefore)
130+
Thread.setDefaultUncaughtExceptionHandler(originalUncaughtExceptionHandler)
131+
assertTrue(uncaughtExceptions.isEmpty(), "Expected no uncaught exceptions, but got $uncaughtExceptions")
123132
}
124133

125134
fun initPoolsBeforeTest() {

0 commit comments

Comments
 (0)