diff --git a/js/js.tests/test/org/jetbrains/k2js/test/config/JsUnitTestReporter.java b/js/js.tests/test/org/jetbrains/k2js/test/config/JsUnitTestReporter.java new file mode 100644 index 00000000000..7cbb5e456d2 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/config/JsUnitTestReporter.java @@ -0,0 +1,147 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.config; + +import closurecompiler.internal.com.google.common.collect.Lists; +import closurecompiler.internal.com.google.common.collect.Maps; +import junit.framework.Assert; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author Pavel Talanov + */ +public class JsUnitTestReporter { + + @NotNull + private final Map finishedTests = Maps.newHashMap(); + @NotNull + private final Map> errors = Maps.newHashMap(); + @NotNull + private final List processedTests = Lists.newArrayList(); + + @Nullable + private String currentTestName; + + //NOTE: usable from Rhino + @SuppressWarnings("UnusedDeclaration") + public void testStart(@NotNull String testName) { + assert currentTestName == null; + currentTestName = testName; + } + + //NOTE: usable from Rhino + @SuppressWarnings("UnusedDeclaration") + public void testFail(@NotNull String testName) { + assert currentTestName != null; + finishedTests.put(testName, false); + currentTestName = null; + } + + //NOTE: usable from Rhino + @SuppressWarnings("UnusedDeclaration") + public void testSuccess(@NotNull String testName) { + assert currentTestName != null; + finishedTests.put(testName, true); + currentTestName = null; + } + + //NOTE: usable from Rhino + @SuppressWarnings("UnusedDeclaration") + public void reportError(@NotNull String message) { + List errorList = errors.get(currentTestName); + if (errorList == null) { + errors.put(currentTestName, Lists.newArrayList(message)); + } + else { + errorList.add(message); + } + } + + @NotNull + private Collection getNewFinishedTests() { + ArrayList finishedTests = Lists.newArrayList(this.finishedTests.keySet()); + finishedTests.removeAll(processedTests); + return finishedTests; + } + + @NotNull + public Collection getErrors(@NotNull String testName) { + List errorList = errors.get(testName); + assert errorList != null; + assert !errorList.isEmpty(); + return errorList; + } + + @NotNull + public Boolean getResult(@NotNull String testName) { + Boolean result = finishedTests.get(testName); + assert result != null; + return result; + } + + @NotNull + public TestSuite createTestSuiteAndFlush() { + final TestSuite suite = new TestSuite("!"); + Collection newFinishedTests = getNewFinishedTests(); + for (String test : newFinishedTests) { + //NOTE: well, it is a test + //noinspection JUnitTestCaseWithNoTests + suite.addTest(new TestCase(test) { + @Override + protected void runTest() throws Throwable { + Boolean result = getResult(getName()); + if (!result) { + Collection errorMessages = getErrors(getName()); + StringBuilder sb = new StringBuilder(); + for (String error : errorMessages) { + sb.append(error); + } + eraseTestInfo(getName()); + Assert.fail(sb.toString()); + } + eraseTestInfo(getName()); + Assert.assertTrue(result); + } + }); + } + processedTests.addAll(newFinishedTests); + return suite; + } + + private void eraseTestInfo(@NotNull String testName) { + errors.remove(testName); + Boolean removed = finishedTests.remove(testName); + assert removed != null; + } + + public void ignoreTests(@NotNull String... testNames) { + for (String testName : testNames) { + if (getResult(testName)) { + System.out.println("Test " + testName + " has passed. And we ignored it! Turn it on?"); + } + eraseTestInfo(testName); + } + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/JsUnitTestBase.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/JsUnitTestBase.java index e711f4b522f..26a0a81cd20 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/JsUnitTestBase.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/JsUnitTestBase.java @@ -17,24 +17,28 @@ package org.jetbrains.k2js.test.semantics; import closurecompiler.internal.com.google.common.collect.Lists; +import com.google.dart.compiler.util.Maps; +import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.test.MultipleFilesTranslationTest; +import org.jetbrains.k2js.test.config.JsUnitTestReporter; import org.jetbrains.k2js.test.config.TestConfigWithUnitTests; import org.jetbrains.k2js.test.rhino.RhinoSystemOutputChecker; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import static org.jetbrains.k2js.test.utils.LibraryFilePathsUtil.getAdditionalLibraryFiles; /** * @author Pavel Talanov */ -public class JsUnitTestBase extends MultipleFilesTranslationTest { +public abstract class JsUnitTestBase extends MultipleFilesTranslationTest { @NotNull private static final String JS_TESTS = pathToTestFilesRoot() + "jsTester/"; @@ -42,6 +46,10 @@ public class JsUnitTestBase extends MultipleFilesTranslationTest { protected static final String JS_TESTS_KT = JS_TESTS + "jsTester.kt"; @NotNull protected static final String JS_TESTS_JS = JS_TESTS + "jsTester.js"; + //NOTE: we use this object to communicate test result from Rhino, it is not necessary to use global objects there + // we can inject those objects in JavaScript every time but this kind of solution will complicate logic a bit + @NotNull + private static final JsUnitTestReporter JS_UNIT_TEST_REPORTER = new JsUnitTestReporter(); public JsUnitTestBase() { super("jsUnitTests/"); @@ -58,7 +66,7 @@ public class JsUnitTestBase extends MultipleFilesTranslationTest { @NotNull @Override protected List additionalKotlinFiles() { - ArrayList result = Lists.newArrayList(); + List result = Lists.newArrayList(); List additionalLibraryFiles = getAdditionalLibraryFiles(); additionalLibraryFiles.add(JS_TESTS_KT); boolean removed = additionalLibraryFiles.remove(Config.LIBRARIES_LOCATION + "/stdlib/testCode.kt"); @@ -67,14 +75,32 @@ public class JsUnitTestBase extends MultipleFilesTranslationTest { return result; } - public void testDummy() throws Exception { - performUnitTest("libraries/stdlib/test/ListTest.kt"); + public void runTestFile(@NotNull String pathToTestFile) throws Exception { + Iterable versions = Collections.singletonList(EcmaVersion.v3); + String testName = pathToTestFile.substring(pathToTestFile.lastIndexOf("/")); + generateJavaScriptFiles(Lists.newArrayList(pathToTestFile), testName, MainCallParameters.noCall(), versions, + TestConfigWithUnitTests.FACTORY); + runRhinoTests(testName, versions, new RhinoSystemOutputChecker("")); } - private void performUnitTest(String... testFiles) throws Exception { - Iterable versions = Collections.singletonList(EcmaVersion.v3); - generateJavaScriptFiles(Lists.newArrayList(testFiles), "myTest", MainCallParameters.noCall(), versions, - TestConfigWithUnitTests.FACTORY); - runRhinoTests("myTest", versions, new RhinoSystemOutputChecker("")); + public static Test createTestSuiteForFile(@NotNull String file, @NotNull String... ignoreFailedTestCases) throws Exception { + performTests(file); + JS_UNIT_TEST_REPORTER.ignoreTests(ignoreFailedTestCases); + return JS_UNIT_TEST_REPORTER.createTestSuiteAndFlush(); + } + + private static void performTests(@NotNull String testFile) throws Exception { + //NOTE: well it doesn't + @SuppressWarnings("JUnitTestCaseWithNoTests") JsUnitTestBase runner = new JsUnitTestBase() { + + }; + runner.setUp(); + runner.runTestFile(testFile); + runner.tearDown(); + } + + @Override + protected Map getRhinoTestVariables() throws Exception { + return Maps.create("jsTestReporter", JS_UNIT_TEST_REPORTER); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibGetOtElseTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibGetOtElseTest.java new file mode 100644 index 00000000000..105e7fa03d0 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibGetOtElseTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +/** + * @author Pavel Talanov + */ +//NOTE: well, it has tests +@SuppressWarnings("JUnitTestCaseWithNoTests") +public class StdLibGetOtElseTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/GetOrElseTest.kt"); + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibListTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibListTest.java new file mode 100644 index 00000000000..8ff754e2c9d --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibListTest.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +/** + * @author Pavel Talanov + */ +//NOTE: well, it has tests +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class StdLibListTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/ListTest.kt", + "ListTest.withIndices", + "ListTest.tail"); + } +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java new file mode 100644 index 00000000000..60798af2ddf --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibMapTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import junit.framework.Test; + +/** + * @author Pavel Talanov + */ +//NOTE: well, it has tests +@SuppressWarnings("JUnitTestCaseWithNoTests") +public final class StdLibMapTest extends JsUnitTestBase { + public static Test suite() throws Exception { + return createTestSuiteForFile("libraries/stdlib/test/js/MapTest.kt"); + } +} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/test/CommonUnitTester.java b/js/js.translator/src/org/jetbrains/k2js/translate/test/CommonUnitTester.java index 7c9146c44d0..508176ae2de 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/test/CommonUnitTester.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/test/CommonUnitTester.java @@ -29,10 +29,6 @@ import static com.google.dart.compiler.util.AstUtil.newInvocation; */ public abstract class CommonUnitTester extends JSTester { - public CommonUnitTester() { - super(); - } - @Override public void constructTestMethodInvocation(@NotNull JsExpression functionToTestCall, @NotNull JsStringLiteral testName) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/test/JSRhinoUnitTester.java b/js/js.translator/src/org/jetbrains/k2js/translate/test/JSRhinoUnitTester.java index 02cabcc0127..f7500368bb3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/test/JSRhinoUnitTester.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/test/JSRhinoUnitTester.java @@ -28,10 +28,6 @@ public final class JSRhinoUnitTester extends CommonUnitTester { public static final JsNameRef TEST_FUN_REF = AstUtil.newQualifiedNameRef("JsTests.test"); - public JSRhinoUnitTester() { - super(); - } - @NotNull @Override protected JsExpression getTestMethodRef() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/test/QUnitTester.java b/js/js.translator/src/org/jetbrains/k2js/translate/test/QUnitTester.java index 50566ad0009..745f7764bdc 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/test/QUnitTester.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/test/QUnitTester.java @@ -28,10 +28,7 @@ public final class QUnitTester extends CommonUnitTester { @NotNull private static final JsNameRef TEST_FUN_REF = AstUtil.newQualifiedNameRef("QUnit.test"); - public QUnitTester() { - super(); - } - + @Override @NotNull protected JsExpression getTestMethodRef() { return TEST_FUN_REF; diff --git a/js/js.translator/testFiles/jsTester/jsTester.js b/js/js.translator/testFiles/jsTester/jsTester.js index 57244907a93..b0f76bc463c 100644 --- a/js/js.translator/testFiles/jsTester/jsTester.js +++ b/js/js.translator/testFiles/jsTester/jsTester.js @@ -15,35 +15,34 @@ */ /*Asserter*/ -var JsTests = (function() { - var out = Kotlin.System.out(); - function setOut(newOut) { - out = newOut; - } - var Asserter = function(out) { - this.out = out; - this.assertTrue = function (message, actual) { - if (!actual) { - this.out.println(message); - } - }; - this.assertEquals = function (message, actual) { - throw null; - }; +var JsTests = (function () { + var reporter = jsTestReporter; + var failedTest = {}; + + var assert = function (isTrue, message) { + if (!isTrue) { + reporter.reportError(message); + throw failedTest; + } }; - var test = function(testName, testFun) { + var test = function (testName, testFun) { + reporter.testStart(testName); try { testFun(); } catch (fail) { - out.println("Test " + testName + " failed"); + if (fail != failedTest) { + reporter.reportError("Unexpected exception " + Kotlin.toString(fail)); + } + reporter.testFail(testName); + return; } + reporter.testSuccess(testName); }; return { - test : test, - Asserter : Asserter, - setOut : setOut + test:test, + assert:assert } })(); diff --git a/js/js.translator/testFiles/jsTester/jsTester.kt b/js/js.translator/testFiles/jsTester/jsTester.kt index 777da914bec..068af79ee30 100644 --- a/js/js.translator/testFiles/jsTester/jsTester.kt +++ b/js/js.translator/testFiles/jsTester/jsTester.kt @@ -5,21 +5,23 @@ import js.* public var asserter : Asserter = JsTestsAsserter() -native("JsTests.Asserter") public class JsTestsAsserter(): Asserter { + public override fun assertTrue(message: String, actual: Boolean) { + assert(actual, message) + } + public override fun assertEquals(message: String, expected: Any?, actual: Any?) { + assert(actual == expected, "$message. Expected <$expected> actual <$actual>") + } + public override fun assertNotNull(message: String, actual: Any?) { + assert(actual != null, message) + } + public override fun assertNull(message: String, actual: Any?) { + assert(actual == null, message) + } + public override fun fail(message: String) { + assert(false, message) + } +} - native - public override fun assertTrue(message: String, actual: Boolean) = noImpl - - native - public override fun assertEquals(message: String, expected: Any?, actual: Any?) = noImpl - - native - public override fun assertNotNull(message: String, actual: Any?) = noImpl - - native - public override fun assertNull(message: String, actual: Any?) = noImpl - - native - public override fun fail(message: String) = noImpl -} \ No newline at end of file +native("JsTests.assert") +public fun assert(value: Boolean, message: String): Unit = js.noImpl \ No newline at end of file diff --git a/js/js.translator/testFiles/jsUnitTests/cases/test/ListTest.kt b/js/js.translator/testFiles/jsUnitTests/cases/test/ListTest.kt deleted file mode 100644 index 352e4a5f497..00000000000 --- a/js/js.translator/testFiles/jsUnitTests/cases/test/ListTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package test.collections - -import java.util.ArrayList -import kotlin.test.* -import org.junit.Test as test - -class ListTest { - - test fun toString() { - val data = arrayList("foo", "bar") - assertEquals("[foo, bar]", data.toString()) - } - - test fun head() { - val data = arrayList("foo", "bar") - assertEquals("foo", data.head) - } - - test fun tail() { - val data = arrayList("foo", "bar", "whatnot") - val actual = data.tail - val expected = arrayList("bar", "whatnot") - assertEquals(expected, actual) - } - - test fun first() { - val data = arrayList("foo", "bar") - assertEquals("foo", data.first) - } - - test fun last() { - val data = arrayList("foo", "bar") - assertEquals("bar", data.last) - } - - /* test fun withIndices() { - val data = arrayList("foo", "bar") - val wis = data.withIndices() - var index = 0 - for (withIndex in wis) { - assertEquals(withIndex._1, index) - assertEquals(withIndex._2, data[index]) - index++ - } - assertEquals(data.size(), index) - }*/ - - test fun lastIndex() { - val emptyData = ArrayList() - val data = arrayList("foo", "bar") - - assertEquals(-1, emptyData.lastIndex) - assertEquals(1, data.lastIndex) - } -}