From 19523339af36aa2cf69285ca8c8194d51bcf95e7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 28 Mar 2024 14:59:22 +0100 Subject: [PATCH] Tests : improve lambda recorder --- .../tests/testutils/lambda/Assertions.kt | 26 ++++---------- .../tests/testutils/lambda/LambdaRecorder.kt | 36 +++++++++++++------ .../testutils/lambda/ParameterMatcher.kt | 2 ++ 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/Assertions.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/Assertions.kt index 4b08a160ba..af241fdea0 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/Assertions.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/Assertions.kt @@ -56,29 +56,17 @@ class ParametersAssertions internal constructor( ) { fun withSequence(vararg matchersSequence: List) { if (parametersSequence.size != matchersSequence.size) { - throw AssertionError("Expected ${matchersSequence.size} parameters, but got ${parametersSequence.size} parameters") + throw AssertionError("Lambda was called ${parametersSequence.size} times, but only ${matchersSequence.size} assertions were provided") } - parametersSequence.zip(matchersSequence).forEach { (parameters, matchers) -> + parametersSequence.zip(matchersSequence).forEachIndexed { invocationIndex, (parameters, matchers) -> if (parameters.size != matchers.size) { - throw AssertionError("Expected ${matchers.size} parameters, but got ${parameters.size} parameters") + throw AssertionError("Expected ${matchers.size} parameters, but got ${parameters.size} parameters during invocation #$invocationIndex") } - parameters.zip(matchers).forEachIndexed { j, (param, matcher) -> + parameters.zip(matchers).forEachIndexed { paramIndex, (param, matcher) -> if (!matcher.match(param)) { - throw AssertionError("Parameter $j does not match the expected value") - } - } - } - for (i in parametersSequence.indices) { - val params = parametersSequence[i] - val checker = matchersSequence[i] - if (params.size != checker.size) { - throw AssertionError("Expected ${checker.size} parameters, but got ${params.size} parameters") - } - for (j in params.indices) { - val param = params[j] - val check = checker[j] - if (!check.match(param)) { - throw AssertionError("Parameter $j does not match the expected value") + throw AssertionError( + "Parameter #$paramIndex does not match the expected value (actual=$param,expected=$matcher) during invocation #$invocationIndex" + ) } } } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt index 52c3dc63a8..b7beaaa5e9 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt @@ -19,10 +19,15 @@ package io.element.android.tests.testutils.lambda /** * A recorder that can be used to record the parameters of lambda invocation. */ -abstract class LambdaRecorder internal constructor() { +abstract class LambdaRecorder internal constructor( + private val assertNoInvocation: Boolean, +) { private val parametersSequence: MutableList> = mutableListOf() internal fun onInvoke(vararg params: Any?) { + if (assertNoInvocation) { + throw AssertionError("This lambda should never be called.") + } parametersSequence.add(params.toList()) } @@ -32,64 +37,73 @@ abstract class LambdaRecorder internal constructor() { } inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, noinline block: () -> R ): LambdaNoParamRecorder { - return LambdaNoParamRecorder(block) + return LambdaNoParamRecorder(ensureNeverCalled, block) } inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, noinline block: (T) -> R ): LambdaOneParamRecorder { - return LambdaOneParamRecorder(block) + return LambdaOneParamRecorder(ensureNeverCalled, block) } inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, noinline block: (T1, T2) -> R ): LambdaTwoParamsRecorder { - return LambdaTwoParamsRecorder(block) + return LambdaTwoParamsRecorder(ensureNeverCalled, block) } inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, noinline block: (T1, T2, T3) -> R ): LambdaThreeParamsRecorder { - return LambdaThreeParamsRecorder(block) + return LambdaThreeParamsRecorder(ensureNeverCalled, block) } inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, noinline block: (T1, T2, T3, T4) -> R ): LambdaFourParamsRecorder { - return LambdaFourParamsRecorder(block) + return LambdaFourParamsRecorder(ensureNeverCalled, block) } -class LambdaNoParamRecorder(val block: () -> R) : LambdaRecorder(), () -> R { +class LambdaNoParamRecorder(ensureNeverCalled: Boolean, val block: () -> R) : LambdaRecorder(ensureNeverCalled), () -> R { override fun invoke(): R { onInvoke() return block() } } -class LambdaOneParamRecorder(val block: (T) -> R) : LambdaRecorder(), (T) -> R { +class LambdaOneParamRecorder(ensureNeverCalled: Boolean, val block: (T) -> R) : LambdaRecorder(ensureNeverCalled), (T) -> R { override fun invoke(p: T): R { onInvoke(p) return block(p) } } -class LambdaTwoParamsRecorder(val block: (T1, T2) -> R) : LambdaRecorder(), (T1, T2) -> R { +class LambdaTwoParamsRecorder(ensureNeverCalled: Boolean, val block: (T1, T2) -> R) : LambdaRecorder(ensureNeverCalled), (T1, T2) -> R { override fun invoke(p1: T1, p2: T2): R { onInvoke(p1, p2) return block(p1, p2) } } -class LambdaThreeParamsRecorder(val block: (T1, T2, T3) -> R) : LambdaRecorder(), (T1, T2, T3) -> R { +class LambdaThreeParamsRecorder(ensureNeverCalled: Boolean, val block: (T1, T2, T3) -> R) : LambdaRecorder( + ensureNeverCalled +), (T1, T2, T3) -> R { override fun invoke(p1: T1, p2: T2, p3: T3): R { onInvoke(p1, p2, p3) return block(p1, p2, p3) } } -class LambdaFourParamsRecorder(val block: (T1, T2, T3, T4) -> R) : LambdaRecorder(), (T1, T2, T3, T4) -> R { +class LambdaFourParamsRecorder(ensureNeverCalled: Boolean, val block: (T1, T2, T3, T4) -> R) : LambdaRecorder( + ensureNeverCalled +), (T1, T2, T3, T4) -> R { override fun invoke(p1: T1, p2: T2, p3: T3, p4: T4): R { onInvoke(p1, p2, p3, p4) return block(p1, p2, p3, p4) diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/ParameterMatcher.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/ParameterMatcher.kt index b070204d28..dd509ed262 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/ParameterMatcher.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/ParameterMatcher.kt @@ -30,6 +30,7 @@ interface ParameterMatcher { */ fun value(expectedValue: T) = object : ParameterMatcher { override fun match(param: Any?) = param == expectedValue + override fun toString(): String = "value($expectedValue)" } /** @@ -38,4 +39,5 @@ fun value(expectedValue: T) = object : ParameterMatcher { */ fun any() = object : ParameterMatcher { override fun match(param: Any?) = true + override fun toString(): String = "any()" }