[JS] Run all js tests in v8

This commit is contained in:
Roman Artemev
2019-03-05 20:18:19 +03:00
committed by romanart
parent 3838a2f648
commit 6b7eba485b
11 changed files with 211 additions and 105 deletions
@@ -21,6 +21,7 @@ import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.test.NashornJsTestChecker; import org.jetbrains.kotlin.js.test.NashornJsTestChecker;
import org.jetbrains.kotlin.js.test.V8JsTestChecker;
import org.jetbrains.kotlin.test.KotlinTestUtils; import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File; import java.io.File;
@@ -31,6 +32,7 @@ import java.util.List;
public class AntTaskJsTest extends AbstractAntTaskTest { public class AntTaskJsTest extends AbstractAntTaskTest {
private static final String JS_OUT_FILE = "out.js"; private static final String JS_OUT_FILE = "out.js";
private static final Boolean useHashorn = Boolean.getBoolean("kotlin.js.useNashorn");
@NotNull @NotNull
private String getTestDataDir() { private String getTestDataDir() {
@@ -58,7 +60,7 @@ public class AntTaskJsTest extends AbstractAntTaskTest {
List<String> filePaths = CollectionsKt.map(fileNames, s -> getOutputFileByName(s).getAbsolutePath()); List<String> filePaths = CollectionsKt.map(fileNames, s -> getOutputFileByName(s).getAbsolutePath());
NashornJsTestChecker.INSTANCE.check(filePaths, "out", "foo", "box", "OK", withModuleSystem); (useHashorn ? NashornJsTestChecker.INSTANCE : V8JsTestChecker.INSTANCE).check(filePaths, "out", "foo", "box", "OK", withModuleSystem);
} }
private void doJsAntTestForPostfixPrefix(@Nullable String prefix, @Nullable String postfix) throws Exception { private void doJsAntTestForPostfixPrefix(@Nullable String prefix, @Nullable String postfix) throws Exception {
@@ -43,6 +43,8 @@ import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapParser
import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapSuccess import org.jetbrains.kotlin.js.parser.sourcemaps.SourceMapSuccess
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
import org.jetbrains.kotlin.js.test.interop.ScriptEngineNashorn
import org.jetbrains.kotlin.js.test.interop.ScriptEngineV8Lazy
import org.jetbrains.kotlin.js.test.utils.* import org.jetbrains.kotlin.js.test.utils.*
import org.jetbrains.kotlin.js.util.TextOutputImpl import org.jetbrains.kotlin.js.util.TextOutputImpl
import org.jetbrains.kotlin.metadata.DebugProtoBuf import org.jetbrains.kotlin.metadata.DebugProtoBuf
@@ -63,6 +65,7 @@ import org.jetbrains.kotlin.utils.JsMetadataVersion
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
import java.io.* import java.io.*
import java.lang.Boolean.getBoolean
import java.nio.charset.Charset import java.nio.charset.Charset
import java.util.regex.Pattern import java.util.regex.Pattern
@@ -84,10 +87,12 @@ abstract class BasicBoxTest(
protected open fun getOutputPostfixFile(testFilePath: String): File? = null protected open fun getOutputPostfixFile(testFilePath: String): File? = null
protected open val runMinifierByDefault: Boolean = false protected open val runMinifierByDefault: Boolean = false
protected open val skipMinification = System.getProperty("kotlin.js.skipMinificationTest", "false")!!.toBoolean() protected open val skipMinification = getBoolean("kotlin.js.skipMinificationTest")
protected open val incrementalCompilationChecksEnabled = true protected open val incrementalCompilationChecksEnabled = true
protected open val testChecker get() = if (runTestInNashorn) NashornJsTestChecker else V8JsTestChecker
fun doTest(filePath: String) { fun doTest(filePath: String) {
doTest(filePath, "OK", MainCallParameters.noCall()) doTest(filePath, "OK", MainCallParameters.noCall())
} }
@@ -262,7 +267,7 @@ abstract class BasicBoxTest(
withModuleSystem: Boolean, withModuleSystem: Boolean,
runtime: JsIrTestRuntime runtime: JsIrTestRuntime
) { ) {
NashornJsTestChecker.check(jsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem) testChecker.check(jsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
} }
protected open fun performAdditionalChecks(generatedJsFiles: List<String>, outputPrefixFile: File?, outputPostfixFile: File?) {} protected open fun performAdditionalChecks(generatedJsFiles: List<String>, outputPrefixFile: File?, outputPostfixFile: File?) {}
@@ -685,7 +690,7 @@ abstract class BasicBoxTest(
val result = engineForMinifier.runAndRestoreContext { val result = engineForMinifier.runAndRestoreContext {
runList.forEach(this::loadFile) runList.forEach(this::loadFile)
overrideAsserter() overrideAsserter()
eval<String>(NashornJsTestChecker.SETUP_KOTLIN_OUTPUT) eval<String>(SETUP_KOTLIN_OUTPUT)
runTestFunction(testModuleName, testPackage, testFunction, withModuleSystem) runTestFunction(testModuleName, testPackage, testFunction, withModuleSystem)
} }
TestCase.assertEquals(expectedResult, result) TestCase.assertEquals(expectedResult, result)
@@ -825,13 +830,15 @@ abstract class BasicBoxTest(
private val CALL_MAIN_PATTERN = Pattern.compile("^// *CALL_MAIN *$", Pattern.MULTILINE) private val CALL_MAIN_PATTERN = Pattern.compile("^// *CALL_MAIN *$", Pattern.MULTILINE)
private val KJS_WITH_FULL_RUNTIME = Pattern.compile("^// *KJS_WITH_FULL_RUNTIME *\$", Pattern.MULTILINE) private val KJS_WITH_FULL_RUNTIME = Pattern.compile("^// *KJS_WITH_FULL_RUNTIME *\$", Pattern.MULTILINE)
@JvmStatic
protected val runTestInNashorn = getBoolean("kotlin.js.useNashorn")
val TEST_MODULE = "JS_TESTS" val TEST_MODULE = "JS_TESTS"
private val DEFAULT_MODULE = "main" private val DEFAULT_MODULE = "main"
private val TEST_FUNCTION = "box" private val TEST_FUNCTION = "box"
private val OLD_MODULE_SUFFIX = "-old" private val OLD_MODULE_SUFFIX = "-old"
const val KOTLIN_TEST_INTERNAL = "\$kotlin_test_internal\$" const val KOTLIN_TEST_INTERNAL = "\$kotlin_test_internal\$"
private val engineForMinifier = if (runTestInNashorn) ScriptEngineNashorn() else ScriptEngineV8Lazy()
private val engineForMinifier = createScriptEngine()
} }
} }
@@ -52,6 +52,8 @@ abstract class BasicIrBoxTest(
super.doTest(filePath, expectedResult, mainCallParameters, coroutinesPackage) super.doTest(filePath, expectedResult, mainCallParameters, coroutinesPackage)
} }
override val testChecker get() = if (runTestInNashorn) NashornIrJsTestChecker() else V8IrJsTestChecker
private val runtimes = mapOf(JsIrTestRuntime.DEFAULT to defaultRuntimeKlib, private val runtimes = mapOf(JsIrTestRuntime.DEFAULT to defaultRuntimeKlib,
JsIrTestRuntime.FULL to fullRuntimeKlib) JsIrTestRuntime.FULL to fullRuntimeKlib)
@@ -141,7 +143,7 @@ abstract class BasicIrBoxTest(
// TODO: should we do anything special for module systems? // TODO: should we do anything special for module systems?
// TODO: return list of js from translateFiles and provide then to this function with other js files // TODO: return list of js from translateFiles and provide then to this function with other js files
V8IrJsTestChecker.check(jsFiles, testModuleName, null, testFunction, expectedResult, withModuleSystem) testChecker.check(jsFiles, testModuleName, null, testFunction, expectedResult, withModuleSystem)
} }
} }
@@ -5,8 +5,6 @@
package org.jetbrains.kotlin.js.test package org.jetbrains.kotlin.js.test
import jdk.nashorn.internal.runtime.ScriptRuntime
import org.jetbrains.kotlin.js.test.interop.GlobalRuntimeContext
import org.jetbrains.kotlin.js.test.interop.ScriptEngine import org.jetbrains.kotlin.js.test.interop.ScriptEngine
import org.jetbrains.kotlin.js.test.interop.ScriptEngineNashorn import org.jetbrains.kotlin.js.test.interop.ScriptEngineNashorn
import org.jetbrains.kotlin.js.test.interop.ScriptEngineV8 import org.jetbrains.kotlin.js.test.interop.ScriptEngineV8
@@ -65,48 +63,39 @@ abstract class AbstractJsTestChecker {
runTestFunction(testModuleName, testPackageName, testFunctionName, withModuleSystem) runTestFunction(testModuleName, testPackageName, testFunctionName, withModuleSystem)
} }
protected abstract fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any?
}
fun ScriptEngine.runAndRestoreContext(
globalObject: GlobalRuntimeContext = getGlobalContext(),
originalState: Map<String, Any?> = globalObject.toMap(),
f: ScriptEngine.() -> Any?
): Any? {
return try {
this.f()
} finally {
for (key in globalObject.keys) {
globalObject[key] = originalState[key] ?: ScriptRuntime.UNDEFINED
}
}
}
abstract class AbstractNashornJsTestChecker: AbstractJsTestChecker() {
private var engineUsageCnt = 0
private var engineCache: ScriptEngine? = null
private var globalObject: GlobalRuntimeContext? = null
private var originalState: Map<String, Any?>? = null
protected val engine
get() = engineCache ?: createScriptEngineForTest().also {
engineCache = it
globalObject = it.getGlobalContext()
originalState = globalObject?.toMap()
}
fun run(files: List<String>) { fun run(files: List<String>) {
run(files) { null } run(files) { null }
} }
abstract fun checkStdout(files: List<String>, expectedResult: String)
protected abstract fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any?
}
fun ScriptEngine.runAndRestoreContext(f: ScriptEngine.() -> Any?): Any? {
return try {
saveState()
f()
} finally {
restoreState()
}
}
abstract class AbstractNashornJsTestChecker : AbstractJsTestChecker() {
private var engineUsageCnt = 0
private var engineCache: ScriptEngineNashorn? = null
protected val engine: ScriptEngineNashorn
get() = engineCache ?: createScriptEngineForTest().also {
engineCache = it
}
protected open fun beforeRun() {} protected open fun beforeRun() {}
override fun run( override fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any? {
files: List<String>,
f: ScriptEngine.() -> Any?
): Any? {
// Recreate the engine once in a while // Recreate the engine once in a while
if (engineUsageCnt++ > 100) { if (engineUsageCnt++ > 100) {
engineUsageCnt = 0 engineUsageCnt = 0
@@ -115,37 +104,46 @@ abstract class AbstractNashornJsTestChecker: AbstractJsTestChecker() {
beforeRun() beforeRun()
return engine.runAndRestoreContext(globalObject!!, originalState!!) { return engine.runAndRestoreContext {
files.forEach(engine::loadFile) files.forEach { loadFile(it) }
engine.f() f()
} }
} }
protected abstract fun createScriptEngineForTest(): ScriptEngine override fun checkStdout(files: List<String>, expectedResult: String) {
}
object NashornJsTestChecker : AbstractNashornJsTestChecker() {
const val SETUP_KOTLIN_OUTPUT = "kotlin.kotlin.io.output = new kotlin.kotlin.io.BufferedOutput();"
private const val GET_KOTLIN_OUTPUT = "kotlin.kotlin.io.output.buffer;"
override fun beforeRun() {
engine.evalVoid(SETUP_KOTLIN_OUTPUT)
}
fun checkStdout(files: List<String>, expectedResult: String) {
run(files) run(files)
val actualResult = engine.eval<String>(GET_KOTLIN_OUTPUT) val actualResult = engine.eval<String>(GET_KOTLIN_OUTPUT)
Assert.assertEquals(expectedResult, actualResult) Assert.assertEquals(expectedResult, actualResult)
} }
override fun createScriptEngineForTest(): ScriptEngine { protected abstract val preloadedScripts: List<String>
val engine = createScriptEngine()
listOf( protected open fun createScriptEngineForTest(): ScriptEngineNashorn {
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js", val engine = ScriptEngineNashorn()
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js" preloadedScripts.forEach { engine.loadFile(it) }
).forEach(engine::loadFile)
return engine
}
}
const val SETUP_KOTLIN_OUTPUT = "kotlin.kotlin.io.output = new kotlin.kotlin.io.BufferedOutput();"
const val GET_KOTLIN_OUTPUT = "kotlin.kotlin.io.output.buffer;"
object NashornJsTestChecker : AbstractNashornJsTestChecker() {
override fun beforeRun() {
engine.evalVoid(SETUP_KOTLIN_OUTPUT)
}
override val preloadedScripts = listOf(
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js"
)
override fun createScriptEngineForTest(): ScriptEngineNashorn {
val engine = super.createScriptEngineForTest()
engine.overrideAsserter() engine.overrideAsserter()
@@ -154,22 +152,61 @@ object NashornJsTestChecker : AbstractNashornJsTestChecker() {
} }
class NashornIrJsTestChecker : AbstractNashornJsTestChecker() { class NashornIrJsTestChecker : AbstractNashornJsTestChecker() {
override fun createScriptEngineForTest(): ScriptEngine { override val preloadedScripts = listOf(
val engine = createScriptEngine() BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
"libraries/stdlib/js/src/js/polyfills.js"
)
}
listOfNotNull( abstract class AbstractV8JsTestChecker : AbstractJsTestChecker() {
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js", protected abstract val engine: ScriptEngineV8
"libraries/stdlib/js/src/js/polyfills.js"
).forEach(engine::loadFile)
return engine override fun checkStdout(files: List<String>, expectedResult: String) {
run(files) {
val actualResult = engine.eval<String>(GET_KOTLIN_OUTPUT)
Assert.assertEquals(expectedResult, actualResult)
}
} }
} }
object V8IrJsTestChecker : AbstractJsTestChecker() { object V8JsTestChecker : AbstractV8JsTestChecker() {
override val engine get() = tlsEngine.get()
private val tlsEngine = object : ThreadLocal<ScriptEngineV8>() {
override fun initialValue() = createV8Engine()
override fun remove() {
get().release()
}
}
private fun createV8Engine(): ScriptEngineV8 {
val v8 = ScriptEngineV8()
listOf(
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js"
).forEach { v8.loadFile(it) }
v8.overrideAsserter()
return v8
}
override fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any? {
engine.evalVoid(SETUP_KOTLIN_OUTPUT)
return engine.runAndRestoreContext {
files.forEach { loadFile(it) }
f()
}
}
}
object V8IrJsTestChecker : AbstractV8JsTestChecker() {
override val engine get() = ScriptEngineV8()
override fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any? { override fun run(files: List<String>, f: ScriptEngine.() -> Any?): Any? {
val v8 = ScriptEngineV8() val v8 = engine
val v = try { val v = try {
files.forEach { v8.loadFile(it) } files.forEach { v8.loadFile(it) }
@@ -1,8 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.test.interop
typealias GlobalRuntimeContext = MutableMap<String, Any?>
@@ -7,10 +7,12 @@ package org.jetbrains.kotlin.js.test.interop
interface ScriptEngine { interface ScriptEngine {
fun <T> eval(script: String): T fun <T> eval(script: String): T
fun getGlobalContext(): GlobalRuntimeContext
fun evalVoid(script: String) fun evalVoid(script: String)
fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T
fun loadFile(path: String) fun loadFile(path: String)
fun release() fun release()
fun <T> releaseObject(t: T) fun <T> releaseObject(t: T)
fun saveState()
fun restoreState()
} }
@@ -6,9 +6,12 @@
package org.jetbrains.kotlin.js.test.interop package org.jetbrains.kotlin.js.test.interop
import jdk.nashorn.api.scripting.NashornScriptEngineFactory import jdk.nashorn.api.scripting.NashornScriptEngineFactory
import jdk.nashorn.internal.runtime.ScriptRuntime
import javax.script.Invocable import javax.script.Invocable
class ScriptEngineNashorn : ScriptEngine { class ScriptEngineNashorn : ScriptEngine {
private var savedState: Map<String, Any?>? = null
// TODO use "-strict" // TODO use "-strict"
private val myEngine = NashornScriptEngineFactory().getScriptEngine("--language=es5", "--no-java", "--no-syntax-extensions") private val myEngine = NashornScriptEngineFactory().getScriptEngine("--language=es5", "--no-java", "--no-syntax-extensions")
@@ -21,10 +24,6 @@ class ScriptEngineNashorn : ScriptEngine {
myEngine.eval(script) myEngine.eval(script)
} }
override fun getGlobalContext(): GlobalRuntimeContext {
return eval("this")
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T { override fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T {
return (myEngine as Invocable).invokeMethod(obj, name, *args) as T return (myEngine as Invocable).invokeMethod(obj, name, *args) as T
@@ -36,4 +35,19 @@ class ScriptEngineNashorn : ScriptEngine {
override fun release() {} override fun release() {}
override fun <T> releaseObject(t: T) {} override fun <T> releaseObject(t: T) {}
private fun getGlobalState(): MutableMap<String, Any?> = eval("this")
override fun saveState() {
savedState = getGlobalState().toMap()
}
override fun restoreState() {
val globalState = getGlobalState()
val originalState = savedState!!
for (key in globalState.keys) {
globalState[key] = originalState[key] ?: ScriptRuntime.UNDEFINED
}
}
} }
@@ -22,10 +22,32 @@ class ScriptEngineV8 : ScriptEngine {
(t as? V8Object)?.release() (t as? V8Object)?.release()
} }
override fun getGlobalContext(): GlobalRuntimeContext { private var savedState: List<String>? = null
val v8result = eval<V8Object>("this")
val context = V8ObjectUtils.toMap(v8result) as GlobalRuntimeContext override fun restoreState() {
return context.also { v8result.release() } val scriptBuilder = StringBuilder()
val globalState = getGlobalPropertyNames()
val originalState = savedState!!
for (key in globalState) {
if (key !in originalState) {
scriptBuilder.append("this['$key'] = void 0;\n")
}
}
evalVoid(scriptBuilder.toString())
}
private fun getGlobalPropertyNames(): List<String> {
val v8Array = eval<V8Array>("Object.getOwnPropertyNames(this)")
val javaArray = V8ObjectUtils.toList(v8Array) as List<String>
v8Array.release()
return javaArray
}
override fun saveState() {
if (savedState == null) {
savedState = getGlobalPropertyNames()
}
} }
private val myRuntime: V8 = V8.createV8Runtime("global", LIBRARY_PATH_BASE) private val myRuntime: V8 = V8.createV8Runtime("global", LIBRARY_PATH_BASE)
@@ -58,4 +80,24 @@ class ScriptEngineV8 : ScriptEngine {
override fun release() { override fun release() {
myRuntime.release() myRuntime.release()
} }
}
class ScriptEngineV8Lazy : ScriptEngine {
override fun <T> eval(script: String) = engine.eval<T>(script)
override fun saveState() = engine.saveState()
override fun evalVoid(script: String) = engine.evalVoid(script)
override fun <T> callMethod(obj: Any, name: String, vararg args: Any?) = engine.callMethod<T>(obj, name, args)
override fun loadFile(path: String) = engine.loadFile(path)
override fun release() = engine.release()
override fun <T> releaseObject(t: T) = engine.releaseObject(t)
override fun restoreState() = engine.restoreState()
private val engine by lazy { ScriptEngineV8() }
} }
@@ -5,12 +5,11 @@
package org.jetbrains.kotlin.js.test.semantics package org.jetbrains.kotlin.js.test.semantics
import com.eclipsesource.v8.V8ScriptException
import com.google.common.collect.Lists import com.google.common.collect.Lists
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.js.facade.MainCallParameters import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.test.BasicBoxTest import org.jetbrains.kotlin.js.test.*
import org.jetbrains.kotlin.js.test.JsIrTestRuntime
import org.jetbrains.kotlin.js.test.NashornJsTestChecker
import java.io.File import java.io.File
import javax.script.ScriptException import javax.script.ScriptException
@@ -28,10 +27,10 @@ abstract class AbstractWebDemoExamplesTest(relativePath: String) : BasicBoxTest(
withModuleSystem: Boolean, withModuleSystem: Boolean,
runtime: JsIrTestRuntime runtime: JsIrTestRuntime
) { ) {
NashornJsTestChecker.checkStdout(jsFiles, expectedResult) testChecker.checkStdout(jsFiles, expectedResult)
} }
@Throws(ScriptException::class) @Throws(ScriptException::class, V8ScriptException::class)
protected fun runMainAndCheckOutput(fileName: String, expectedResult: String, vararg args: String) { protected fun runMainAndCheckOutput(fileName: String, expectedResult: String, vararg args: String) {
doTest(pathToTestDir + fileName, expectedResult, MainCallParameters.mainWithArguments(Lists.newArrayList(*args))) doTest(pathToTestDir + fileName, expectedResult, MainCallParameters.mainWithArguments(Lists.newArrayList(*args)))
} }
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.js.test.semantics package org.jetbrains.kotlin.js.test.semantics
import com.eclipsesource.v8.V8ScriptException
import org.jetbrains.kotlin.js.test.BasicBoxTest import org.jetbrains.kotlin.js.test.BasicBoxTest
import org.jetbrains.kotlin.js.test.NashornJsTestChecker
import java.io.File import java.io.File
import javax.script.ScriptException import javax.script.ScriptException
@@ -44,9 +44,10 @@ class MultiModuleOrderTest : BasicBoxTest(pathToTestGroupDir, testGroupDir) {
val mainJsFile = File(parentDir, "$name-main_v5.js").path val mainJsFile = File(parentDir, "$name-main_v5.js").path
val libJsFile = File(parentDir, "$name-lib_v5.js").path val libJsFile = File(parentDir, "$name-lib_v5.js").path
try { try {
NashornJsTestChecker.run(listOf(mainJsFile, libJsFile)) testChecker.run(listOf(mainJsFile, libJsFile))
} }
catch (e: ScriptException) { catch (e: RuntimeException) {
assertTrue(e is ScriptException || e is V8ScriptException)
val message = e.message!! val message = e.message!!
assertTrue("Exception message should contain reference to dependency (lib)", "'lib'" in message) assertTrue("Exception message should contain reference to dependency (lib)", "'lib'" in message)
assertTrue("Exception message should contain reference to module that failed to load (main)", "'main'" in message) assertTrue("Exception message should contain reference to module that failed to load (main)", "'main'" in message)
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.js.test.semantics; package org.jetbrains.kotlin.js.test.semantics;
import com.eclipsesource.v8.V8ScriptException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.script.ScriptException; import javax.script.ScriptException;
@@ -52,11 +53,18 @@ public final class WebDemoCanvasExamplesTest extends AbstractWebDemoExamplesTest
fail(); fail();
} }
catch (ScriptException e) { catch (ScriptException e) {
String expectedErrorMessage = "ReferenceError: \"" + firstUnknownSymbolEncountered + "\" is not defined"; verifyException("\"" + firstUnknownSymbolEncountered + "\"", e.getMessage());
assertTrue("Unexpected error when running compiled canvas examples with rhino.\n" + }
"Expected: " + expectedErrorMessage + "\n" + catch (V8ScriptException e) {
"Actual: " + e.getMessage(), verifyException(firstUnknownSymbolEncountered, e.getJSMessage());
e.getMessage().startsWith(expectedErrorMessage));
} }
} }
private static void verifyException(@NotNull String firstUnknownSymbolEncountered, @NotNull String message) {
String expectedErrorMessage = "ReferenceError: " + firstUnknownSymbolEncountered + " is not defined";
assertTrue("Unexpected error when running compiled canvas examples with rhino.\n" +
"Expected: " + expectedErrorMessage + "\n" +
"Actual: " + message,
message.startsWith(expectedErrorMessage));
}
} }