From 22694fa6b01e862ecf408ba04f585ecdc9c26f16 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Wed, 1 May 2019 08:54:43 +0300 Subject: [PATCH] Make assertFails(With) inline-only functions So that the lambda passed to these functions can capture suspend function calls. #KT-31194 Fixed --- .../src/main/kotlin/kotlin/test/Assertions.kt | 46 ++++++++++++++----- .../main/kotlin/kotlin/test/AssertionsH.kt | 14 ++---- .../js/src/main/kotlin/kotlin/test/JsImpl.kt | 30 ++++++------ .../jvm/src/main/kotlin/AssertionsImpl.kt | 43 +++++++---------- 4 files changed, 70 insertions(+), 63 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 31d3ba0eaa7..927210f53a8 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -107,7 +107,9 @@ fun <@OnlyInputTypes T> expect(expected: T, message: String?, block: () -> T) { * @return An exception that was expected to be thrown and was successfully caught. * The returned exception can be inspected further, for example by asserting its property values. */ -fun assertFails(block: () -> Unit): Throwable = assertFails(null, block) +@InlineOnly +inline fun assertFails(block: () -> Unit): Throwable = + checkResultIsFailure(null, runCatching(block)) /** * Asserts that given function [block] fails by throwing an exception. @@ -118,14 +120,20 @@ fun assertFails(block: () -> Unit): Throwable = assertFails(null, block) * The returned exception can be inspected further, for example by asserting its property values. */ @SinceKotlin("1.1") -fun assertFails(message: String?, block: () -> Unit): Throwable { - try { - block() - } catch (e: Throwable) { - assertEquals(e.message, e.message) // success path assertion for qunit - return e - } - asserter.fail(messagePrefix(message) + "Expected an exception to be thrown, but was completed successfully.") +@InlineOnly +inline fun assertFails(message: String?, block: () -> Unit): Throwable = + checkResultIsFailure(message, runCatching(block)) + +@PublishedApi +internal fun checkResultIsFailure(message: String?, blockResult: Result): Throwable { + blockResult.fold( + onSuccess = { + asserter.fail(messagePrefix(message) + "Expected an exception to be thrown, but was completed successfully.") + }, + onFailure = { e -> + return e + } + ) } /** Asserts that a [block] fails with a specific exception of type [T] being thrown. @@ -136,7 +144,7 @@ fun assertFails(message: String?, block: () -> Unit): Throwable { * The returned exception can be inspected further, for example by asserting its property values. */ @InlineOnly -inline fun assertFailsWith(message: String? = null, noinline block: () -> Unit): T = +inline fun assertFailsWith(message: String? = null, block: () -> Unit): T = assertFailsWith(T::class, message, block) /** @@ -145,7 +153,21 @@ inline fun assertFailsWith(message: String? = null, noin * @return An exception of the expected exception type [T] that successfully caught. * The returned exception can be inspected further, for example by asserting its property values. */ -fun assertFailsWith(exceptionClass: KClass, block: () -> Unit): T = assertFailsWith(exceptionClass, null, block) +@InlineOnly +inline fun assertFailsWith(exceptionClass: KClass, block: () -> Unit): T = assertFailsWith(exceptionClass, null, block) + + +/** + * Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. + * + * If the assertion fails, the specified [message] is used unless it is null as a prefix for the failure message. + * + * @return An exception of the expected exception type [T] that successfully caught. + * The returned exception can be inspected further, for example by asserting its property values. + */ +@InlineOnly +inline fun assertFailsWith(exceptionClass: KClass, message: String?, block: () -> Unit): T = + checkResultIsFailure(exceptionClass, message, runCatching(block)) /** diff --git a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/AssertionsH.kt b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/AssertionsH.kt index 8e8c34fcb8b..1ba78fb2462 100644 --- a/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/AssertionsH.kt +++ b/libraries/kotlin.test/common/src/main/kotlin/kotlin/test/AssertionsH.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -14,12 +14,6 @@ import kotlin.reflect.KClass */ expect fun todo(block: () -> Unit) -/** - * Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. - * - * If the assertion fails, the specified [message] is used unless it is null as a prefix for the failure message. - * - * @return An exception of the expected exception type [T] that successfully caught. - * The returned exception can be inspected further, for example by asserting its property values. - */ -expect fun assertFailsWith(exceptionClass: KClass, message: String?, block: () -> Unit): T +/** Asserts that a [blockResult] is a failure with the specific exception type being thrown. */ +@PublishedApi +internal expect fun checkResultIsFailure(exceptionClass: KClass, message: String?, blockResult: Result): T diff --git a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/JsImpl.kt b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/JsImpl.kt index ba125245931..f9cb5cd9a5e 100644 --- a/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/JsImpl.kt +++ b/libraries/kotlin.test/js/src/main/kotlin/kotlin/test/JsImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -18,20 +18,20 @@ actual fun todo(block: () -> Unit) { } -/** - * Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. - * - * If the assertion fails, the specified [message] is used unless it is null as a prefix for the failure message. - * - * @return An exception of the expected exception type [T] that successfully caught. - * The returned exception can be inspected further, for example by asserting its property values. - */ -actual fun assertFailsWith(exceptionClass: KClass, message: String?, block: () -> Unit): T { - val exception = assertFails(message, block) - assertTrue(exceptionClass.isInstance(exception), messagePrefix(message) + "Expected an exception of $exceptionClass to be thrown, but was $exception") - - @Suppress("UNCHECKED_CAST") - return exception as T +@PublishedApi +internal actual fun checkResultIsFailure(exceptionClass: KClass, message: String?, blockResult: Result): T { + blockResult.fold( + onSuccess = { + asserter.fail(messagePrefix(message) + "Expected an exception of $exceptionClass to be thrown, but was completed successfully.") + }, + onFailure = { e -> + if (exceptionClass.isInstance(e)) { + @Suppress("UNCHECKED_CAST") + return e as T + } + asserter.fail(messagePrefix(message) + "Expected an exception of $exceptionClass to be thrown, but was $e") + } + ) } diff --git a/libraries/kotlin.test/jvm/src/main/kotlin/AssertionsImpl.kt b/libraries/kotlin.test/jvm/src/main/kotlin/AssertionsImpl.kt index b26c969c04a..13ec6e318d0 100644 --- a/libraries/kotlin.test/jvm/src/main/kotlin/AssertionsImpl.kt +++ b/libraries/kotlin.test/jvm/src/main/kotlin/AssertionsImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 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. */ @@ -11,35 +11,26 @@ package kotlin.test import kotlin.internal.* import kotlin.reflect.* -/** Asserts that a [block] fails with a specific exception being thrown. */ -private fun assertFailsWithImpl(exceptionClass: Class, message: String?, block: () -> Unit): T { - try { - block() - } catch (e: Throwable) { - if (exceptionClass.isInstance(e)) { - @Suppress("UNCHECKED_CAST") - return e as T +/** Asserts that a [blockResult] is a failure with the specific exception type being thrown. */ +@PublishedApi +internal actual fun checkResultIsFailure(exceptionClass: KClass, message: String?, blockResult: Result): T { + blockResult.fold( + onSuccess = { + val msg = messagePrefix(message) + asserter.fail(msg + "Expected an exception of ${exceptionClass.java} to be thrown, but was completed successfully.") + }, + onFailure = { e -> + if (exceptionClass.java.isInstance(e)) { + @Suppress("UNCHECKED_CAST") + return e as T + } + + asserter.fail(messagePrefix(message) + "Expected an exception of ${exceptionClass.java} to be thrown, but was $e") } - - asserter.fail(messagePrefix(message) + "Expected an exception of $exceptionClass to be thrown, but was $e") - } - - val msg = messagePrefix(message) - asserter.fail(msg + "Expected an exception of $exceptionClass to be thrown, but was completed successfully.") + ) } -/** - * Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. - * - * If the assertion fails, the specified [message] is used unless it is null as a prefix for the failure message. - * - * @return An exception of the expected exception type [T] that successfully caught. - * The returned exception can be inspected further, for example by asserting its property values. - */ -actual fun assertFailsWith(exceptionClass: KClass, message: String?, block: () -> Unit): T = - assertFailsWithImpl(exceptionClass.java, message, block) - /** * Takes the given [block] of test code and _doesn't_ execute it.