• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines.exceptions
6 
7 import kotlinx.coroutines.*
8 import java.io.*
9 import java.util.*
10 import kotlin.coroutines.*
11 import kotlin.test.*
12 
13 /**
14  * Proxy for [Throwable.getSuppressed] for tests, which are compiled for both JDK 1.6 and JDK 1.8,
15  * but run only under JDK 1.8
16  */
17 @Suppress("ConflictingExtensionProperty")
18 actual val Throwable.suppressed: Array<Throwable> get() {
19     val method = this::class.java.getMethod("getSuppressed") ?: error("This test can only be run using JDK 1.7")
20     @Suppress("UNCHECKED_CAST")
21     return method.invoke(this) as Array<Throwable>
22 }
23 
checkExceptionnull24 internal inline fun <reified T : Throwable> checkException(exception: Throwable): Boolean {
25     assertTrue(exception is T)
26     assertTrue(exception.suppressed.isEmpty())
27     assertNull(exception.cause)
28     return true
29 }
30 
checkCyclesnull31 internal fun checkCycles(t: Throwable) {
32     val sw = StringWriter()
33     t.printStackTrace(PrintWriter(sw))
34     assertFalse(sw.toString().contains("CIRCULAR REFERENCE"))
35 }
36 
37 class CapturingHandler : AbstractCoroutineContextElement(CoroutineExceptionHandler),
38     CoroutineExceptionHandler
39 {
40     private var unhandled: ArrayList<Throwable>? = ArrayList()
41 
<lambda>null42     override fun handleException(context: CoroutineContext, exception: Throwable) = synchronized<Unit>(this) {
43         unhandled!!.add(exception)
44     }
45 
getExceptionsnull46     fun getExceptions(): List<Throwable> = synchronized(this) {
47         return unhandled!!.also { unhandled = null }
48     }
49 
<lambda>null50     fun getException(): Throwable = synchronized(this) {
51         val size = unhandled!!.size
52         assert(size == 1) { "Expected one unhandled exception, but have $size: $unhandled" }
53         return unhandled!![0].also { unhandled = null }
54     }
55 }
56 
captureExceptionsRunnull57 internal fun captureExceptionsRun(
58     context: CoroutineContext = EmptyCoroutineContext,
59     block: suspend CoroutineScope.() -> Unit
60 ): Throwable {
61     val handler = CapturingHandler()
62     runBlocking(context + handler, block = block)
63     return handler.getException()
64 }
65 
captureMultipleExceptionsRunnull66 internal fun captureMultipleExceptionsRun(
67     context: CoroutineContext = EmptyCoroutineContext,
68     block: suspend CoroutineScope.() -> Unit
69 ): List<Throwable> {
70     val handler = CapturingHandler()
71     runBlocking(context + handler, block = block)
72     return handler.getExceptions()
73 }
74