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
6 
7 import kotlinx.coroutines.*
8 import org.junit.*
9 import org.junit.Assert.*
10 import java.lang.reflect.*
11 import java.util.concurrent.*
12 
13 @Suppress("DEPRECATION")
14 class CommonPoolTest {
15     private inline fun <T> Try(block: () -> T) = try { block() } catch (e: Throwable) { null }
16 
17     @Test
18     fun testIsGoodCommonPool() {
19         // Test only on JDKs that has all we need
20         val fjpClass = Try { Class.forName("java.util.concurrent.ForkJoinPool") } ?: return
21         val wtfClass = Try { Class.forName("java.util.concurrent.ForkJoinPool${'$'}ForkJoinWorkerThreadFactory") } ?: return
22         val dwtfClass = Try { Class.forName("java.util.concurrent.ForkJoinPool${'$'}DefaultForkJoinWorkerThreadFactory") } ?: return
23         // We need private constructor to create "broken" FJP instance
24         val fjpCtor = Try { fjpClass.getDeclaredConstructor(
25             Int::class.java,
26             wtfClass,
27             Thread.UncaughtExceptionHandler::class.java,
28             Int::class.java,
29             String::class.java
30         ) } ?: return
31         fjpCtor.isAccessible = true
32         val dwtfCtor = Try { dwtfClass.getDeclaredConstructor() } ?: return
33         dwtfCtor.isAccessible = true
34         // Create bad pool
35         val fjp0: ExecutorService = createFJP(0, fjpCtor, dwtfCtor) ?: return
36         assertFalse(CommonPool.isGoodCommonPool(fjpClass, fjp0))
37         fjp0.shutdown()
38         // Create good pool
39         val fjp1: ExecutorService = createFJP(1, fjpCtor, dwtfCtor) ?: return
40         assertTrue(CommonPool.isGoodCommonPool(fjpClass, fjp1))
41         fjp1.shutdown()
42     }
43 
44     private fun createFJP(
45         parallelism: Int,
46         fjpCtor: Constructor<out Any>,
47         dwtfCtor: Constructor<out Any>
48     ): ExecutorService? = Try {
49         fjpCtor.newInstance(
50             parallelism,
51             dwtfCtor.newInstance(),
52             Thread.getDefaultUncaughtExceptionHandler(),
53             0,
54             "Worker"
55         )
56     } as? ExecutorService
57 }