diff --git a/js/js.libraries/src/core/javalang.kt b/js/js.libraries/src/core/javalang.kt index 379c4999b2f..485a3619260 100644 --- a/js/js.libraries/src/core/javalang.kt +++ b/js/js.libraries/src/core/javalang.kt @@ -27,6 +27,9 @@ public class NumberFormatException(message: String? = null) : RuntimeException(m @library public class NullPointerException(message: String? = null) : RuntimeException(message) {} +@library +public class AssertionError(message: String? = null) : Error(message) {} + @library public interface Runnable { public open fun run() : Unit; diff --git a/js/js.libraries/src/stdlib/testCode.kt b/js/js.libraries/src/stdlib/testCode.kt index 887bd9e2973..dbdca10fac9 100644 --- a/js/js.libraries/src/stdlib/testCode.kt +++ b/js/js.libraries/src/stdlib/testCode.kt @@ -18,14 +18,23 @@ public var asserter: Asserter = QUnitAsserter() public class QUnitAsserter(): Asserter { public override fun assertTrue(lazyMessage: () -> String?, actual: Boolean) { - QUnit.ok(actual, lazyMessage()) + assertTrue(actual, lazyMessage()) } public override fun assertTrue(message: String?, actual: Boolean) { QUnit.ok(actual, message) + if (!actual) failWithMessage(message) } - public override fun fail(message: String?) { + public override fun fail(message: String?): Nothing { QUnit.ok(false, message) + failWithMessage(message) + } + + private fun failWithMessage(message: String?): Nothing { + if (message == null) + throw AssertionError() + else + throw AssertionError(message) } } \ No newline at end of file diff --git a/js/js.translator/testData/jsTester/jsTester.js b/js/js.translator/testData/jsTester/jsTester.js index 0b90fb1c61f..660ad3cbae6 100644 --- a/js/js.translator/testData/jsTester/jsTester.js +++ b/js/js.translator/testData/jsTester/jsTester.js @@ -21,11 +21,15 @@ var JsTests = (function () { var assert = function (isTrue, message) { if (!isTrue) { - reporter.reportError(message); - throw failedTest; + fail(message); } }; + var fail = function (message) { + reporter.reportError(message); + throw failedTest; + }; + var init = function () { init = function() {}; Kotlin.modules["JS_TESTS"].kotlin.test.init(); @@ -49,6 +53,7 @@ var JsTests = (function () { }; return { test: test, - assert: assert + assert: assert, + fail: fail } })(); diff --git a/js/js.translator/testData/jsTester/jsTester.kt b/js/js.translator/testData/jsTester/jsTester.kt index badbeaa6c21..b1a46e3f6d6 100644 --- a/js/js.translator/testData/jsTester/jsTester.kt +++ b/js/js.translator/testData/jsTester/jsTester.kt @@ -7,10 +7,11 @@ fun init() { } public class JsTestsAsserter() : Asserter { - public override fun fail(message: String?) { - assert(false, message) - } + public override fun fail(message: String?): Nothing = failWithMessage(message) } @native("JsTests.assert") public fun assert(value: Boolean, message: String?): Unit = noImpl + +@native("JsTests.fail") +private fun failWithMessage(message: String?): Nothing = noImpl diff --git a/js/js.translator/testData/kotlin_lib.js b/js/js.translator/testData/kotlin_lib.js index 15e632484ef..627c807ea2f 100644 --- a/js/js.translator/testData/kotlin_lib.js +++ b/js/js.translator/testData/kotlin_lib.js @@ -200,6 +200,7 @@ Kotlin.UnsupportedOperationException = createClassNowWithMessage(Kotlin.RuntimeException); Kotlin.IndexOutOfBoundsException = createClassNowWithMessage(Kotlin.RuntimeException); Kotlin.IOException = createClassNowWithMessage(Kotlin.Exception); + Kotlin.AssertionError = createClassNowWithMessage(Kotlin.Error); Kotlin.throwNPE = function (message) { throw new Kotlin.NullPointerException(message); diff --git a/libraries/kotlin.test/junit/src/main/kotlin/JUnitSupport.kt b/libraries/kotlin.test/junit/src/main/kotlin/JUnitSupport.kt index 68e78497a2e..a0aa575d5c4 100644 --- a/libraries/kotlin.test/junit/src/main/kotlin/JUnitSupport.kt +++ b/libraries/kotlin.test/junit/src/main/kotlin/JUnitSupport.kt @@ -35,7 +35,9 @@ object JUnitAsserter : Asserter { Assert.assertNull(message ?: "actual value is not null", actual) } - override fun fail(message : String?) { + override fun fail(message : String?): Nothing { Assert.fail(message) + // should not get here + throw AssertionError(message) } } diff --git a/libraries/kotlin.test/shared/src/main/kotlin.jvm/kotlin/test/TestAssertionsJVM.kt b/libraries/kotlin.test/shared/src/main/kotlin.jvm/kotlin/test/TestAssertionsJVM.kt index df406968306..6502211ef28 100644 --- a/libraries/kotlin.test/shared/src/main/kotlin.jvm/kotlin/test/TestAssertionsJVM.kt +++ b/libraries/kotlin.test/shared/src/main/kotlin.jvm/kotlin/test/TestAssertionsJVM.kt @@ -22,11 +22,9 @@ fun assertFailsWith(exceptionClass: Class, message: String?, return e as T } asserter.fail((message?.let { "$it. " } ?: "") + "Expected an exception of type $exceptionClass to be thrown, but was $e") - throw e } val msg = message?.let { "$it. " } ?: "" asserter.fail(msg + "Expected an exception of type $exceptionClass to be thrown, but was completed successfully.") - throw IllegalStateException(msg + "Should have failed.") } /** Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. */ diff --git a/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/DefaultAsserter.kt b/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/DefaultAsserter.kt index eed8581329a..b5cedf80a61 100644 --- a/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/DefaultAsserter.kt +++ b/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/DefaultAsserter.kt @@ -5,7 +5,7 @@ package kotlin.test */ class DefaultAsserter() : Asserter { - override fun fail(message: String?) { + override fun fail(message: String?): Nothing { if (message == null) throw AssertionError() else diff --git a/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/TestAssertions.kt b/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/TestAssertions.kt index 635b3a4395f..4d7699b6727 100644 --- a/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/TestAssertions.kt +++ b/libraries/kotlin.test/shared/src/main/kotlin/kotlin/test/TestAssertions.kt @@ -63,7 +63,7 @@ fun assertNull(actual: Any?, message: String? = null) { } /** Marks a test as having failed if this point in the execution path is reached, with an optional [message]. */ -fun fail(message: String? = null) { +fun fail(message: String? = null): Nothing { asserter.fail(message) } @@ -81,16 +81,13 @@ fun <@OnlyInputTypes T> expect(expected: T, message: String?, block: () -> T) { fun fails(block: () -> Unit): Throwable? = assertFails(block) /** Asserts that given function [block] fails by throwing an exception. */ -fun assertFails(block: () -> Unit): Throwable? { - var thrown: Throwable? = null +fun assertFails(block: () -> Unit): Throwable { try { block() } catch (e: Throwable) { - thrown = e + return e } - if (thrown == null) - asserter.fail("Expected an exception to be thrown") - return thrown + asserter.fail("Expected an exception to be thrown") } /** @@ -103,7 +100,7 @@ interface Asserter { * * @param message the message to report. */ - fun fail(message: String?): Unit + fun fail(message: String?): Nothing /** * Asserts that the specified value is `true`.