Skip to content

Commit

Permalink
test: add CompletableFutureUseTest.kt
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed Feb 13, 2023
1 parent 3fa3ff7 commit af03680
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions src/test/java/io/foldright/cffu/CompletableFutureUseTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.foldright.cffu

import io.kotest.core.spec.style.AnnotationSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldNotStartWith
import io.kotest.matchers.string.shouldStartWith
import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicLong
import kotlin.random.Random
import kotlin.random.nextULong

class CompletableFutureUseTest : AnnotationSpec() {
/**
* - `Async` methods(e.g. `runAsync`/`thenRunAsync`, etc.) can set `executor`;
* if executor argument is absent use default executor of [CompletableFuture.ASYNC_POOL] (normally is a [ForkJoinPool]).
* - non-`Async` methods use the executor of previous [CompletableFuture].
*/
@Test
fun executor_inheritance_behavior() {
val testThread = Thread.currentThread()
CompletableFuture
.runAsync {
Thread.currentThread() shouldNotBe testThread

Thread.currentThread().name shouldNotStartWith threadNamePrefix
}
.thenRunAsync({
Thread.currentThread().name shouldStartWith threadNamePrefix
}, executor) // !! switched executor !!
.thenRun {
// when run NOT async,
// executor is INHERITED after switch.
Thread.currentThread().name shouldStartWith threadNamePrefix
}
.thenRunAsync {
// when run ASYNC,
//
// - executor is NOT inherited after switch!!
// - use the DEFAULT EXECUTOR of CompletableFuture, if no executor specified.
Thread.currentThread().name shouldNotStartWith threadNamePrefix
}
.join()
}

////////////////////////////////////////////////////////////////////////////////
// executor field
////////////////////////////////////////////////////////////////////////////////

private lateinit var executor: ExecutorService

private val threadNamePrefix = "CompletableFutureUseTest_${Random.nextULong()}-"

@BeforeAll
fun beforeAll() {
val threadFactory = ThreadFactory { r ->
val counter = AtomicLong()
Thread(r).apply {
name = "$threadNamePrefix${counter.getAndIncrement()}"
isDaemon = true
}
}
executor = ThreadPoolExecutor(
4, 4, 1, TimeUnit.MINUTES,
ArrayBlockingQueue(10), threadFactory
)
}

@AfterAll
fun afterAll() {
executor.shutdown()
executor.awaitTermination(1, TimeUnit.SECONDS) shouldBe true
}
}

0 comments on commit af03680

Please sign in to comment.