From e66eeefe2a4ae5531bd120643efb6420fd849ae0 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 17 Mar 2021 13:53:33 +0300 Subject: [PATCH] kotlin-test: assertIs and assertIsNot KT-45296 - Rename assertNotIs to assertIsNot - Extract parts of implementation to helper internal PublishedApi functions in order to inline minimum amount of code at use sites - Remove PublishedApi from messagePrefix, no longer needed --- .../src/main/kotlin/kotlin/test/Assertions.kt | 23 +++++++++++--- .../src/main/kotlin/kotlin/test/Utils.kt | 3 +- .../kotlin/test/tests/BasicAssertionsTest.kt | 31 ++++++++++++------- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt index 789d73f2988..7bdec45de32 100644 --- a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt +++ b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Assertions.kt @@ -17,6 +17,7 @@ import kotlin.internal.* import kotlin.jvm.JvmName import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass +import kotlin.reflect.KType import kotlin.reflect.typeOf /** @@ -80,26 +81,38 @@ fun <@OnlyInputTypes T> assertNotSame(illegal: T, actual: T, message: String? = /** * Asserts that [value] is of type [T], with an optional [message]. * - * Note that due to type erasure the type check may be partial (e.g. assertIs>(value) + * Note that due to type erasure the type check may be partial (e.g. `assertIs>(value)` * only checks for the class being [List] and not the type of its elements because it's erased). */ @SinceKotlin("1.5") @InlineOnly +@OptIn(ExperimentalStdlibApi::class) inline fun assertIs(value: Any?, message: String? = null) { contract { returns() implies (value is T) } - asserter.assertTrue({ messagePrefix(message) + "Expected value to be of type <${typeOf()}>, actual <${value?.let { it::class }}>." }, value is T) + assertIsOfType(value, typeOf(), value is T, message) +} + +@PublishedApi +internal fun assertIsOfType(value: Any?, type: KType, result: Boolean, message: String?) { + asserter.assertTrue({ messagePrefix(message) + "Expected value to be of type <$type>, actual <${value?.let { it::class }}>." }, result) } /** * Asserts that [value] is not of type [T], with an optional [message]. * - * Note that due to type erasure the type check may be partial (e.g. assertNotIs>(value) + * Note that due to type erasure the type check may be partial (e.g. `assertIsNot>(value)` * only checks for the class being [List] and not the type of its elements because it's erased). */ @SinceKotlin("1.5") @InlineOnly -inline fun assertNotIs(value: Any?, message: String? = null) { - asserter.assertFalse({ messagePrefix(message) + "Expected value to not be of type <${typeOf()}>" }, value is T) +@OptIn(ExperimentalStdlibApi::class) +inline fun assertIsNot(value: Any?, message: String? = null) { + assertIsNotOfType(value, typeOf(), value !is T, message) +} + +@PublishedApi +internal fun assertIsNotOfType(@Suppress("UNUSED_PARAMETER") value: Any?, type: KType, result: Boolean, message: String?) { + asserter.assertTrue({ messagePrefix(message) + "Expected value to not be of type <$type>." }, result) } /** Asserts that the [actual] value is not `null`, with an optional [message]. */ diff --git a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Utils.kt b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Utils.kt index c6bb6f14301..a022582f870 100644 --- a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Utils.kt +++ b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/Utils.kt @@ -1,11 +1,10 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlin.test -@PublishedApi // called from inline assert functions internal fun messagePrefix(message: String?) = if (message == null) "" else "$message. " internal expect fun lookupAsserter(): Asserter diff --git a/libraries/kotlin.test/common/src/test/kotlin/kotlin/test/tests/BasicAssertionsTest.kt b/libraries/kotlin.test/common/src/test/kotlin/kotlin/test/tests/BasicAssertionsTest.kt index 799e12544aa..7e68f55f2a4 100644 --- a/libraries/kotlin.test/common/src/test/kotlin/kotlin/test/tests/BasicAssertionsTest.kt +++ b/libraries/kotlin.test/common/src/test/kotlin/kotlin/test/tests/BasicAssertionsTest.kt @@ -1,10 +1,11 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package kotlin.test.tests +import kotlin.reflect.typeOf import kotlin.test.* class BasicAssertionsTest { @@ -207,30 +208,36 @@ class BasicAssertionsTest { } @Test - fun testAssertIs() { + fun testAssertIsOfType() { val s: Any = "test" assertIs(s) assertEquals(4, s.length) } + @OptIn(ExperimentalStdlibApi::class) @Test - fun testAssertIsFails() { + fun testAssertIsOfTypeFails() { val error = checkFailedAssertion { assertIs("test") } - assertTrue(error.message.startsWith("Expected value to be of type")) - assertTrue(error.message.contains("Int")) - assertTrue(error.message.contains("String")) + val message = assertNotNull(error.message) + val onFailure = "Actual message: $message" + assertTrue(message.startsWith("Expected value to be of type"), onFailure) + assertTrue(message.contains(typeOf().toString()), onFailure) + assertTrue(message.contains("String"), onFailure) } @Test - fun testAssertNotIs() { - assertNotIs("test") + fun testAssertIsNotOfType() { + assertIsNot("test") } @Test - fun testAssertNotIsFails() { - val error = checkFailedAssertion { assertNotIs(1) } - assertTrue(error.message.startsWith("Expected value to not be of type")) - assertTrue(error.message.contains("Int")) + @OptIn(ExperimentalStdlibApi::class) + fun testAssertIsNotOfTypeFails() { + val error = checkFailedAssertion { assertIsNot(1) } + val message = assertNotNull(error.message) + val onFailure = "Actual message: $message" + assertTrue(message.startsWith("Expected value to not be of type"), onFailure) + assertTrue(message.contains(typeOf().toString()), onFailure) } }