diff --git a/.idea/runConfigurations/run_tests.xml b/.idea/runConfigurations/run_tests.xml
index 1ee65a010..91d14d00b 100644
--- a/.idea/runConfigurations/run_tests.xml
+++ b/.idea/runConfigurations/run_tests.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TTimeZone.java b/classlib/src/main/java/org/teavm/classlib/java/util/TTimeZone.java
index bbc78d9a9..daaac4736 100644
--- a/classlib/src/main/java/org/teavm/classlib/java/util/TTimeZone.java
+++ b/classlib/src/main/java/org/teavm/classlib/java/util/TTimeZone.java
@@ -21,6 +21,7 @@ import org.teavm.classlib.impl.tz.DateTimeZone;
import org.teavm.classlib.impl.tz.DateTimeZoneProvider;
import org.teavm.classlib.impl.tz.FixedDateTimeZone;
import org.teavm.classlib.impl.unicode.CLDRHelper;
+import org.teavm.classlib.java.lang.TThreadInterruptHandler;
/**
* {@code TimeZone} represents a time zone offset, taking into account
@@ -152,7 +153,8 @@ public abstract class TTimeZone implements Serializable, Cloneable {
*/
public static TTimeZone getDefault() {
if (defaultTz == null) {
- defaultTz = new TIANATimeZone(DateTimeZoneProvider.detectTimezone());
+ //defaultTz = new TIANATimeZone(DateTimeZoneProvider.detectTimezone());
+ defaultTz = TTimeZone.getTimeZone("UTC");
}
return (TTimeZone) defaultTz.clone();
}
diff --git a/tests/src/test/java/org/teavm/classlib/java/util/TestService.java b/tests/src/test/java/org/teavm/classlib/java/util/TestService.java
index ac31722a0..503088362 100644
--- a/tests/src/test/java/org/teavm/classlib/java/util/TestService.java
+++ b/tests/src/test/java/org/teavm/classlib/java/util/TestService.java
@@ -15,14 +15,6 @@
*/
package org.teavm.classlib.java.util;
-import org.junit.runner.RunWith;
-import org.teavm.junit.TeaVMTestRunner;
-
-/**
- *
- * @author Alexey Andreev
- */
-@RunWith(TeaVMTestRunner.class)
public interface TestService {
void foo();
}
diff --git a/tests/teavm-tests.iml b/tests/teavm-tests.iml
index 874da67d8..d00130667 100644
--- a/tests/teavm-tests.iml
+++ b/tests/teavm-tests.iml
@@ -52,24 +52,24 @@
-
+
-
+
-
+
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java b/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
deleted file mode 100644
index 0a2a45328..000000000
--- a/tools/cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2014 Alexey Andreev.
- *
- * 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.teavm.cli;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.PosixParser;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.testing.TestAdapter;
-import org.teavm.tooling.TeaVMToolException;
-import org.teavm.tooling.testing.TeaVMTestTool;
-
-/**
- *
- * @author Alexey Andreev
- */
-public final class TeaVMTestRunner {
- private TeaVMTestRunner() {
- }
-
- @SuppressWarnings("static-access")
- public static void main(String[] args) {
- Options options = new Options();
- options.addOption(OptionBuilder
- .withArgName("directory")
- .hasArg()
- .withDescription("a directory where to put generated files (current directory by default)")
- .withLongOpt("targetdir")
- .create('d'));
- options.addOption(OptionBuilder
- .withDescription("causes TeaVM to generate minimized JavaScript file")
- .withLongOpt("minify")
- .create("m"));
- options.addOption(OptionBuilder
- .withArgName("number")
- .hasArg()
- .withDescription("how many threads should TeaVM run")
- .withLongOpt("threads")
- .create("t"));
- options.addOption(OptionBuilder
- .withArgName("class name")
- .hasArg()
- .withDescription("qualified class name of test adapter")
- .withLongOpt("adapter")
- .create("a"));
- options.addOption(OptionBuilder
- .hasArg()
- .hasOptionalArgs()
- .withArgName("class name")
- .withDescription("qualified class names of transformers")
- .withLongOpt("transformers")
- .create("T"));
- options.addOption(OptionBuilder
- .withDescription("Incremental build")
- .withLongOpt("incremental")
- .create('i'));
-
- if (args.length == 0) {
- printUsage(options);
- return;
- }
- CommandLineParser parser = new PosixParser();
- CommandLine commandLine;
- try {
- commandLine = parser.parse(options, args);
- } catch (ParseException e) {
- printUsage(options);
- return;
- }
-
- TeaVMTestTool tool = new TeaVMTestTool();
- tool.setTargetDirectory(new File(commandLine.getOptionValue("d", ".")));
- tool.setMinifying(commandLine.hasOption("m"));
- try {
- tool.setNumThreads(Integer.parseInt(commandLine.getOptionValue("t", "1")));
- } catch (NumberFormatException e) {
- System.err.println("Invalid number specified for -t option");
- printUsage(options);
- return;
- }
- if (commandLine.hasOption("a")) {
- tool.setAdapter(instantiateAdapter(commandLine.getOptionValue("a")));
- }
- if (commandLine.hasOption("T")) {
- for (String transformerType : commandLine.getOptionValues("T")) {
- tool.getTransformers().add(instantiateTransformer(transformerType));
- }
- }
- if (commandLine.hasOption('i')) {
- tool.setIncremental(true);
- }
-
- args = commandLine.getArgs();
- if (args.length == 0) {
- System.err.println("You did not specify any test classes");
- printUsage(options);
- return;
- }
- tool.getTestClasses().addAll(Arrays.asList(args));
-
- tool.setLog(new ConsoleTeaVMToolLog());
- tool.getProperties().putAll(System.getProperties());
- long start = System.currentTimeMillis();
- try {
- tool.generate();
- } catch (TeaVMToolException e) {
- e.printStackTrace(System.err);
- System.exit(-2);
- }
- System.out.println("Operation took " + (System.currentTimeMillis() - start) + " milliseconds");
- }
-
- private static TestAdapter instantiateAdapter(String adapterName) {
- Class> adapterClass;
- try {
- adapterClass = Class.forName(adapterName, true, TeaVMTestRunner.class.getClassLoader());
- } catch (ClassNotFoundException e) {
- System.err.println("Adapter not found: " + adapterName);
- System.exit(-1);
- return null;
- }
- if (!TestAdapter.class.isAssignableFrom(adapterClass)) {
- System.err.println("Adapter class does not implement TestAdapter: " + adapterName);
- System.exit(-1);
- return null;
- }
- Constructor> cons;
- try {
- cons = adapterClass.getConstructor();
- } catch (NoSuchMethodException e) {
- System.err.println("Adapter class does not contain no-arg constructor: " + adapterName);
- System.exit(-1);
- return null;
- }
-
- try {
- return (TestAdapter) cons.newInstance();
- } catch (IllegalAccessException | InstantiationException e) {
- System.err.println("Error instantiating adapter: " + adapterName);
- e.printStackTrace(System.err);
- System.exit(-1);
- return null;
- } catch (InvocationTargetException e) {
- System.err.println("Error instantiating adapter: " + adapterName);
- e.getTargetException().printStackTrace(System.err);
- System.exit(-1);
- return null;
- }
- }
-
- private static ClassHolderTransformer instantiateTransformer(String transformerName) {
- Class> adapterClass;
- try {
- adapterClass = Class.forName(transformerName, true, TeaVMTestRunner.class.getClassLoader());
- } catch (ClassNotFoundException e) {
- System.err.println("Transformer not found: " + transformerName);
- System.exit(-1);
- return null;
- }
- if (!ClassHolderTransformer.class.isAssignableFrom(adapterClass)) {
- System.err.println("Transformer class does not implement ClassHolderTransformer: " + transformerName);
- System.exit(-1);
- return null;
- }
- Constructor> cons;
- try {
- cons = adapterClass.getConstructor();
- } catch (NoSuchMethodException e) {
- System.err.println("Transformer class does not contain no-arg constructor: " + transformerName);
- System.exit(-1);
- return null;
- }
-
- try {
- return (ClassHolderTransformer) cons.newInstance();
- } catch (IllegalAccessException | InstantiationException e) {
- System.err.println("Error instantiating transformer: " + transformerName);
- e.printStackTrace(System.err);
- System.exit(-1);
- return null;
- } catch (InvocationTargetException e) {
- System.err.println("Error instantiating transformer: " + transformerName);
- e.getTargetException().printStackTrace(System.err);
- System.exit(-1);
- return null;
- }
- }
-
- private static void printUsage(Options options) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("java " + TeaVMTestRunner.class.getName() + " [OPTIONS] test_name {test_name}", options);
- System.exit(-1);
- }
-}
diff --git a/tools/junit/pom.xml b/tools/junit/pom.xml
index e22e24331..c931d5118 100644
--- a/tools/junit/pom.xml
+++ b/tools/junit/pom.xml
@@ -53,7 +53,7 @@
net.sourceforge.htmlunit
htmlunit
- 2.18
+ 2.19
diff --git a/tools/junit/src/main/java/org/teavm/junit/ExceptionHelper.java b/tools/junit/src/main/java/org/teavm/junit/ExceptionHelper.java
index d9d88435a..f4ad9ed20 100644
--- a/tools/junit/src/main/java/org/teavm/junit/ExceptionHelper.java
+++ b/tools/junit/src/main/java/org/teavm/junit/ExceptionHelper.java
@@ -15,10 +15,6 @@
*/
package org.teavm.junit;
-/**
- *
- * @author Alexey Andreev
- */
final class ExceptionHelper {
private ExceptionHelper() {
}
diff --git a/tools/junit/src/main/java/org/teavm/junit/HtmlUnitRunStrategy.java b/tools/junit/src/main/java/org/teavm/junit/HtmlUnitRunStrategy.java
index 7265ff1d3..40c315018 100644
--- a/tools/junit/src/main/java/org/teavm/junit/HtmlUnitRunStrategy.java
+++ b/tools/junit/src/main/java/org/teavm/junit/HtmlUnitRunStrategy.java
@@ -29,33 +29,56 @@ import net.sourceforge.htmlunit.corejs.javascript.Function;
import net.sourceforge.htmlunit.corejs.javascript.NativeJavaObject;
import org.apache.commons.io.IOUtils;
-public class HtmlUnitRunStrategy implements TestRunStrategy {
+class HtmlUnitRunStrategy implements TestRunStrategy {
+ private ThreadLocal webClient = new ThreadLocal<>();
+ private ThreadLocal page = new ThreadLocal<>();
+ private int runs;
+
@Override
public void beforeThread() {
+ init();
}
@Override
public void afterThread() {
+ cleanUp();
}
@Override
public String runTest(TestRun run) throws IOException {
- try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
- HtmlPage page = webClient.getPage("about:blank");
- page.executeJavaScript(readFile(new File(run.getBaseDirectory(), "runtime.js")));
+ if (++runs == 50) {
+ runs = 0;
+ cleanUp();
+ init();
+ }
- AsyncResult asyncResult = new AsyncResult();
- Function function = (Function) page.executeJavaScript(readResource("teavm-htmlunit-adapter.js"))
- .getJavaScriptResult();
- Object[] args = new Object[] { new NativeJavaObject(function, asyncResult, AsyncResult.class) };
- page.executeJavaScriptFunctionIfPossible(function, function, args, page);
+ page.get().executeJavaScript(readFile(new File(run.getBaseDirectory(), "runtime.js")));
+ page.get().executeJavaScript(readFile(new File(run.getBaseDirectory(), "test.js")));
- page.executeJavaScript(readFile(new File(run.getBaseDirectory(), "test.js")));
- page.cleanUp();
- for (WebWindow window : webClient.getWebWindows()) {
- window.getJobManager().removeAllJobs();
- }
- return (String) asyncResult.getResult();
+ AsyncResult asyncResult = new AsyncResult();
+ Function function = (Function) page.get().executeJavaScript(readResource("teavm-htmlunit-adapter.js"))
+ .getJavaScriptResult();
+ Object[] args = new Object[] { new NativeJavaObject(function, asyncResult, AsyncResult.class) };
+ page.get().executeJavaScriptFunctionIfPossible(function, function, args, page.get());
+ return (String) asyncResult.getResult();
+ }
+
+ private void cleanUp() {
+ page.get().cleanUp();
+ for (WebWindow window : webClient.get().getWebWindows()) {
+ window.getJobManager().removeAllJobs();
+ }
+ page.remove();
+ webClient.get().close();
+ webClient.remove();
+ }
+
+ private void init() {
+ webClient.set(new WebClient(BrowserVersion.CHROME));
+ try {
+ page.set(webClient.get().getPage("about:blank"));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
}
diff --git a/tools/junit/src/main/java/org/teavm/junit/SeleniumRunStrategy.java b/tools/junit/src/main/java/org/teavm/junit/SeleniumRunStrategy.java
index 6c3f7d8cb..62db69ea6 100644
--- a/tools/junit/src/main/java/org/teavm/junit/SeleniumRunStrategy.java
+++ b/tools/junit/src/main/java/org/teavm/junit/SeleniumRunStrategy.java
@@ -28,10 +28,11 @@ import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
-public class SeleniumRunStrategy implements TestRunStrategy {
+class SeleniumRunStrategy implements TestRunStrategy {
private URL url;
private ThreadLocal webDriver = new ThreadLocal<>();
private ThreadLocal commandsSent = new ThreadLocal<>();
+ private int rebootRate = Integer.getInteger("teavm.junit.js.selenium.rebootAfter", 1000);
public SeleniumRunStrategy(URL url) {
this.url = url;
@@ -54,7 +55,7 @@ public class SeleniumRunStrategy implements TestRunStrategy {
@Override
public String runTest(TestRun run) throws IOException {
commandsSent.set(commandsSent.get() + 1);
- if (commandsSent.get().equals(20)) {
+ if (commandsSent.get().equals(100)) {
commandsSent.set(0);
webDriver.get().close();
webDriver.get().quit();
diff --git a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
index 7c5e5a5d1..a8b9006b2 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java
@@ -66,6 +66,7 @@ import org.teavm.vm.TeaVMBuilder;
public class TeaVMTestRunner extends Runner {
private static final String PATH_PARAM = "teavm.junit.target";
private static final String RUNNER = "teavm.junit.js.runner";
+ private static final String THREAD_COUNT = "teavm.junit.js.threads";
private static final String SELENIUM_URL = "teavm.junit.js.selenium.url";
private static final int stopTimeout = 15000;
private Class> testClass;
@@ -83,6 +84,16 @@ public class TeaVMTestRunner extends Runner {
private static volatile ScheduledFuture> cleanupFuture;
private CountDownLatch latch;
+ static {
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ synchronized (TeaVMTestRunner.class) {
+ cleanupFuture = null;
+ runner.stop();
+ runner.waitForCompletion();
+ }
+ }));
+ }
+
public TeaVMTestRunner(Class> testClass) throws InitializationError {
this.testClass = testClass;
classLoader = TeaVMTestRunner.class.getClassLoader();
@@ -167,14 +178,27 @@ public class TeaVMTestRunner extends Runner {
boolean run = false;
boolean success = true;
+ MethodHolder methodHolder = classHolder.getMethod(getDescriptor(child));
+ Set> expectedExceptions = new HashSet<>();
+ for (String exceptionName : testAdapter.getExpectedExceptions(methodHolder)) {
+ try {
+ expectedExceptions.add(Class.forName(exceptionName, false, classLoader));
+ } catch (ClassNotFoundException e) {
+ notifier.fireTestFailure(new Failure(describeChild(child), e));
+ notifier.fireTestFinished(describeChild(child));
+ latch.countDown();
+ return;
+ }
+ }
+
if (!child.isAnnotationPresent(SkipJVM.class)
&& !child.getDeclaringClass().isAnnotationPresent(SkipJVM.class)) {
run = true;
- success = runInJvm(child, notifier);
+ success = runInJvm(child, notifier, expectedExceptions);
}
if (success && outputDir != null) {
- runInTeaVM(child, notifier);
+ runInTeaVM(child, notifier, expectedExceptions);
} else {
if (!run) {
notifier.fireTestIgnored(describeChild(child));
@@ -184,18 +208,7 @@ public class TeaVMTestRunner extends Runner {
}
}
- private boolean runInJvm(Method child, RunNotifier notifier) {
- MethodHolder methodHolder = classHolder.getMethod(getDescriptor(child));
- Set> expectedExceptions = new HashSet<>();
- for (String exceptionName : testAdapter.getExpectedExceptions(methodHolder)) {
- try {
- expectedExceptions.add(Class.forName(exceptionName, false, classLoader));
- } catch (ClassNotFoundException e) {
- notifier.fireTestFailure(new Failure(describeChild(child), e));
- return false;
- }
- }
-
+ private boolean runInJvm(Method child, RunNotifier notifier, Set> expectedExceptions) {
Object instance;
try {
instance = testClass.newInstance();
@@ -233,22 +246,29 @@ public class TeaVMTestRunner extends Runner {
return true;
}
- private boolean runInTeaVM(Method child, RunNotifier notifier) {
+ private boolean runInTeaVM(Method child, RunNotifier notifier, Set> expectedExceptions) {
+ Description description = describeChild(child);
+
CompileResult compileResult;
try {
compileResult = compileTest(child);
} catch (IOException e) {
- notifier.fireTestFailure(new Failure(describeChild(child), e));
+ notifier.fireTestFailure(new Failure(description, e));
return false;
}
if (!compileResult.success) {
- notifier.fireTestFailure(new Failure(describeChild(child),
+ notifier.fireTestFailure(new Failure(description,
new AssertionError(compileResult.errorMessage)));
return false;
}
- Description description = describeChild(child);
+ if (runStrategy == null) {
+ notifier.fireTestFinished(description);
+ latch.countDown();
+ return true;
+ }
+
TestRunCallback callback = new TestRunCallback() {
@Override
public void complete() {
@@ -264,7 +284,7 @@ public class TeaVMTestRunner extends Runner {
TestRun run = new TestRun(compileResult.file.getParentFile(), child,
new MethodReference(testClass.getName(), getDescriptor(child)),
- description, callback);
+ description, callback, expectedExceptions);
submitRun(run);
return true;
}
@@ -277,6 +297,11 @@ public class TeaVMTestRunner extends Runner {
if (runner == null) {
runner = new TestRunner(runStrategy);
+ try {
+ runner.setNumThreads(Integer.parseInt(System.getProperty(THREAD_COUNT, "1")));
+ } catch (NumberFormatException e) {
+ runner.setNumThreads(1);
+ }
runner.init();
}
runner.run(run);
diff --git a/tools/junit/src/main/java/org/teavm/junit/TestRun.java b/tools/junit/src/main/java/org/teavm/junit/TestRun.java
index c03eb5a68..54299debc 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TestRun.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TestRun.java
@@ -17,23 +17,28 @@ package org.teavm.junit;
import java.io.File;
import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import org.junit.runner.Description;
import org.teavm.model.MethodReference;
-public class TestRun {
+class TestRun {
private File baseDirectory;
private Method method;
private MethodReference reference;
private Description description;
private TestRunCallback callback;
+ private Set> expectedExceptions;
- public TestRun(File baseDirectory, Method method, MethodReference reference, Description description,
- TestRunCallback callback) {
+ TestRun(File baseDirectory, Method method, MethodReference reference, Description description,
+ TestRunCallback callback, Set> expectedExceptions) {
this.baseDirectory = baseDirectory;
this.method = method;
this.reference = reference;
this.description = description;
this.callback = callback;
+ this.expectedExceptions = Collections.unmodifiableSet(new HashSet<>(expectedExceptions));
}
public File getBaseDirectory() {
@@ -55,4 +60,8 @@ public class TestRun {
public TestRunCallback getCallback() {
return callback;
}
+
+ public Set> getExpectedExceptions() {
+ return expectedExceptions;
+ }
}
diff --git a/tools/junit/src/main/java/org/teavm/junit/TestRunCallback.java b/tools/junit/src/main/java/org/teavm/junit/TestRunCallback.java
index bf53f0606..221696f8b 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TestRunCallback.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TestRunCallback.java
@@ -15,7 +15,7 @@
*/
package org.teavm.junit;
-public interface TestRunCallback {
+interface TestRunCallback {
void complete();
void error(Throwable e);
diff --git a/tools/junit/src/main/java/org/teavm/junit/TestRunStrategy.java b/tools/junit/src/main/java/org/teavm/junit/TestRunStrategy.java
index fd9d4af96..56241ce7b 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TestRunStrategy.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TestRunStrategy.java
@@ -17,7 +17,7 @@ package org.teavm.junit;
import java.io.IOException;
-public interface TestRunStrategy {
+interface TestRunStrategy {
void beforeThread();
void afterThread();
diff --git a/tools/junit/src/main/java/org/teavm/junit/TestRunner.java b/tools/junit/src/main/java/org/teavm/junit/TestRunner.java
index 4286ddc5b..54ceb990c 100644
--- a/tools/junit/src/main/java/org/teavm/junit/TestRunner.java
+++ b/tools/junit/src/main/java/org/teavm/junit/TestRunner.java
@@ -22,18 +22,15 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunNotifier;
-import org.teavm.model.MethodReference;
-public class TestRunner {
+class TestRunner {
private int numThreads = 1;
private TestRunStrategy strategy;
private BlockingQueue taskQueue = new LinkedBlockingQueue<>();
private CountDownLatch latch;
private volatile boolean stopped;
- public TestRunner(TestRunStrategy strategy) {
+ TestRunner(TestRunStrategy strategy) {
this.strategy = strategy;
}
@@ -73,7 +70,19 @@ public class TestRunner {
public void stop() {
stopped = true;
- taskQueue.add(null);
+ taskQueue.add(() -> { });
+ }
+
+ public void waitForCompletion() {
+ while (true) {
+ try {
+ if (latch.await(1000, TimeUnit.MILLISECONDS)) {
+ break;
+ }
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
}
public void run(TestRun run) {
@@ -81,7 +90,6 @@ public class TestRunner {
}
private void runImpl(TestRun run) {
- MethodReference ref = run.getReference();
try {
String result = strategy.runTest(run);
if (result == null) {
@@ -93,17 +101,38 @@ public class TestRunner {
String status = resultObject.get("status").asText();
switch (status) {
case "ok":
- run.getCallback().complete();
+ if (!run.getExpectedExceptions().isEmpty()) {
+ run.getCallback().error(new AssertionError("Expected exception was not thrown"));
+ } else {
+ run.getCallback().complete();
+ }
break;
case "exception": {
String stack = resultObject.get("stack").asText();
- String exception = resultObject.get("exception").asText();
- run.getCallback().error(new AssertionError(exception + "\n" + exception));
+ String exception = resultObject.has("exception") ? resultObject.get("exception").asText() : null;
+ Class> exceptionClass;
+ if (exception != null) {
+ try {
+ exceptionClass = Class.forName(exception, false, TestRunner.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ exceptionClass = null;
+ }
+ } else {
+ exceptionClass = null;
+ }
+ if (exceptionClass != null) {
+ Class> caught = exceptionClass;
+ if (run.getExpectedExceptions().stream().anyMatch(e -> e.isAssignableFrom(caught))) {
+ run.getCallback().complete();
+ break;
+ }
+ }
+ run.getCallback().error(new AssertionError(exception + "\n" + stack));
run.getCallback().complete();
break;
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
run.getCallback().error(e);
run.getCallback().complete();
}
diff --git a/tools/junit/src/main/resources/teavm-htmlunit-adapter.js b/tools/junit/src/main/resources/teavm-htmlunit-adapter.js
index c245ef607..53032f2f7 100644
--- a/tools/junit/src/main/resources/teavm-htmlunit-adapter.js
+++ b/tools/junit/src/main/resources/teavm-htmlunit-adapter.js
@@ -1,38 +1,37 @@
function main(callback) {
- var JUnitClient = {};
- JUnitClient.run = function() {
- $rt_startThread(function() {
- var thread = $rt_nativeThread();
- var instance;
- var ptr = 0;
- var message;
- if (thread.isResuming()) {
- ptr = thread.pop();
- instance = thread.pop();
- }
- loop: while (true) { switch (ptr) {
- case 0:
- try {
- runTest();
- } catch (e) {
+ $rt_startThread(function () {
+ var thread = $rt_nativeThread();
+ var instance;
+ var ptr = 0;
+ var message;
+ if (thread.isResuming()) {
+ ptr = thread.pop();
+ instance = thread.pop();
+ }
+ loop: while (true) {
+ switch (ptr) {
+ case 0:
+ try {
+ runTest();
+ } catch (e) {
+ message = {};
+ makeErrorMessage(message, e);
+ break loop;
+ }
+ if (thread.isSuspending()) {
+ thread.push(instance);
+ thread.push(ptr);
+ return;
+ }
message = {};
- JUnitClient.makeErrorMessage(message, e);
+ message.status = "ok";
break loop;
- }
- if (thread.isSuspending()) {
- thread.push(instance);
- thread.push(ptr);
- return;
- }
- message = {};
- message.status = "ok";
- break loop;
- }}
- callback.complete(JSON.stringify(message));
- })
- };
+ }
+ }
+ callback.complete(JSON.stringify(message));
+ });
- JUnitClient.makeErrorMessage = function(message, e) {
+ function makeErrorMessage(message, e) {
message.status = "exception";
var stack = e.stack;
if (e.$javaException && e.$javaException.constructor.$meta) {
@@ -42,7 +41,5 @@ function main(callback) {
message.stack += exceptionMessage ? $rt_ustr(exceptionMessage) : "";
}
message.stack += "\n" + stack;
- };
-
- window.JUnitClient = JUnitClient;
+ }
}
\ No newline at end of file
diff --git a/tools/junit/src/main/resources/teavm-selenium-adapter.js b/tools/junit/src/main/resources/teavm-selenium-adapter.js
index f122df3df..715c9acdd 100644
--- a/tools/junit/src/main/resources/teavm-selenium-adapter.js
+++ b/tools/junit/src/main/resources/teavm-selenium-adapter.js
@@ -29,7 +29,7 @@ $rt_startThread(function() {
runTest();
} catch (e) {
message = {};
- JUnitClient.makeErrorMessage(message, e);
+ makeErrorMessage(message, e);
break loop;
}
if (thread.isSuspending()) {
diff --git a/tools/junit/teavm-junit.iml b/tools/junit/teavm-junit.iml
index 579ab3b8a..cbd5028f7 100644
--- a/tools/junit/teavm-junit.iml
+++ b/tools/junit/teavm-junit.iml
@@ -41,25 +41,25 @@
-
+
-
+
-
+
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file