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 }