• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines.test
6 
7 import kotlinx.atomicfu.*
8 import kotlin.test.*
9 import kotlin.time.*
10 import kotlin.time.Duration.Companion.seconds
11 
12 /**
13  * The number of milliseconds that is sure not to pass [assertRunsFast].
14  */
15 const val SLOW = 100_000L
16 
17 /**
18  * Asserts that a block completed within [timeout].
19  */
20 @OptIn(ExperimentalTime::class)
assertRunsFastnull21 inline fun <T> assertRunsFast(timeout: Duration, block: () -> T): T {
22     val result: T
23     val elapsed = TimeSource.Monotonic.measureTime { result = block() }
24     assertTrue("Should complete in $timeout, but took $elapsed") { elapsed < timeout }
25     return result
26 }
27 
28 /**
29  * Asserts that a block completed within two seconds.
30  */
assertRunsFastnull31 inline fun <T> assertRunsFast(block: () -> T): T = assertRunsFast(2.seconds, block)
32 
33 /**
34  * Runs [test], and then invokes [block], passing to it the lambda that functionally behaves
35  * the same way [test] does.
36 */
37 fun testResultMap(block: (() -> Unit) -> Unit, test: () -> TestResult): TestResult = testResultChain(
38     block = test,
39     after = {
40         block { it.getOrThrow() }
41         createTestResult { }
42     }
43 )
44 
45 /**
46  * Chains together [block] and [after], passing the result of [block] to [after].
47  */
testResultChainnull48 expect fun testResultChain(block: () -> TestResult, after: (Result<Unit>) -> TestResult): TestResult
49 
50 fun testResultChain(vararg chained: (Result<Unit>) -> TestResult): TestResult =
51     if (chained.isEmpty()) {
52         createTestResult { }
53     } else {
<lambda>null54         testResultChain(block = {
55             chained[0](Result.success(Unit))
56         }) {
57             testResultChain(*chained.drop(1).toTypedArray())
58         }
59     }
60 
61 class TestException(message: String? = null): Exception(message)
62 
63 /**
64  * A class inheriting from which allows to check the execution order inside tests.
65  *
66  * @see TestBase
67  */
68 open class OrderedExecutionTestBase {
69     private val actionIndex = atomic(0)
70     private val finished = atomic(false)
71 
72     /** Expect the next action to be [index] in order. */
expectnull73     protected fun expect(index: Int) {
74         val wasIndex = actionIndex.incrementAndGet()
75         check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
76     }
77 
78     /** Expect this action to be final, with the given [index]. */
finishnull79     protected fun finish(index: Int) {
80         expect(index)
81         check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" }
82     }
83 
84     @AfterTest
ensureFinishCallsnull85     fun ensureFinishCalls() {
86         assertTrue(finished.value || actionIndex.value == 0, "Expected `finish` to be called")
87     }
88 }
89 
voidnull90 internal fun <T> T.void() { }
91 
92 @OptionalExpectation
93 expect annotation class NoJs()
94 
95 @OptionalExpectation
96 expect annotation class NoNative()
97