diff --git a/tests/src/test/js/run.sh b/tests/src/test/js/run.sh new file mode 100755 index 000000000..44fa483af --- /dev/null +++ b/tests/src/test/js/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +npm run build +node start.js ../../../target/js-tests/ 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 338989c30..324259230 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java +++ b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java @@ -229,13 +229,9 @@ public class TeaVMTestRunner extends Runner implements Filterable { for (TeaVMTestConfiguration configuration : configurations) { try { - TestRun run = compileByTeaVM(child, notifier, expectedExceptions, configuration, onSuccess.get(0)); + TestRun run = compileByTeaVM(child, notifier, configuration, onSuccess.get(0)); if (run != null) { runs.add(run); - } else { - notifier.fireTestFinished(description); - latch.countDown(); - return; } } catch (Throwable e) { notifier.fireTestFailure(new Failure(description, e)); @@ -293,7 +289,7 @@ public class TeaVMTestRunner extends Runner implements Filterable { return true; } - private TestRun compileByTeaVM(Method child, RunNotifier notifier, Set> expectedExceptions, + private TestRun compileByTeaVM(Method child, RunNotifier notifier, TeaVMTestConfiguration configuration, Consumer onComplete) { Description description = describeChild(child); @@ -330,7 +326,7 @@ public class TeaVMTestRunner extends Runner implements Filterable { return new TestRun(compileResult.file.getParentFile(), child, new MethodReference(testClass.getName(), getDescriptor(child)), - description, callback, expectedExceptions); + description, callback); } private void submitRun(TestRun run) { diff --git a/tools/junit/src/main/java/org/teavm/junit/TestEntryPointTransformer.java b/tools/junit/src/main/java/org/teavm/junit/TestEntryPointTransformer.java index ae1c27cc9..b089b40ac 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TestEntryPointTransformer.java +++ b/tools/junit/src/main/java/org/teavm/junit/TestEntryPointTransformer.java @@ -15,14 +15,20 @@ */ package org.teavm.junit; +import org.junit.Test; import org.teavm.diagnostics.Diagnostics; +import org.teavm.model.AnnotationReader; +import org.teavm.model.AnnotationValue; +import org.teavm.model.BasicBlock; import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassReaderSource; import org.teavm.model.ElementModifier; import org.teavm.model.MethodHolder; +import org.teavm.model.MethodReader; import org.teavm.model.MethodReference; import org.teavm.model.Program; +import org.teavm.model.TryCatchBlock; import org.teavm.model.ValueType; import org.teavm.model.emit.ProgramEmitter; import org.teavm.model.emit.ValueEmitter; @@ -33,7 +39,7 @@ class TestEntryPointTransformer implements ClassHolderTransformer, TeaVMPlugin { private String runnerClassName; private MethodReference testMethod; - public TestEntryPointTransformer(String runnerClassName, MethodReference testMethod) { + TestEntryPointTransformer(String runnerClassName, MethodReference testMethod) { this.runnerClassName = runnerClassName; this.testMethod = testMethod; } @@ -75,7 +81,27 @@ class TestEntryPointTransformer implements ClassHolderTransformer, TeaVMPlugin { pe.getField(TestEntryPoint.class, "testCase", Object.class) .cast(ValueType.object(testMethod.getClassName())) .invokeSpecial(testMethod); - pe.exit(); + + MethodReader testMethodReader = innerSource.resolve(testMethod); + AnnotationReader testAnnotation = testMethodReader.getAnnotations().get(Test.class.getName()); + AnnotationValue throwsValue = testAnnotation.getValue("expected"); + if (throwsValue != null) { + BasicBlock handler = pe.getProgram().createBasicBlock(); + TryCatchBlock tryCatch = new TryCatchBlock(); + tryCatch.setExceptionType(((ValueType.Object) throwsValue.getJavaClass()).getClassName()); + tryCatch.setHandler(handler); + pe.getBlock().getTryCatchBlocks().add(tryCatch); + + BasicBlock nextBlock = pe.getProgram().createBasicBlock(); + pe.jump(nextBlock); + pe.enter(nextBlock); + pe.construct(AssertionError.class, pe.constant("Expected exception not thrown")).raise(); + + pe.enter(handler); + pe.exit(); + } else { + pe.exit(); + } return pe.getProgram(); } } 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 54299debc..2487f2636 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TestRun.java +++ b/tools/junit/src/main/java/org/teavm/junit/TestRun.java @@ -17,9 +17,6 @@ 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; @@ -29,16 +26,14 @@ class TestRun { private MethodReference reference; private Description description; private TestRunCallback callback; - private Set> expectedExceptions; TestRun(File baseDirectory, Method method, MethodReference reference, Description description, - TestRunCallback callback, Set> expectedExceptions) { + TestRunCallback callback) { 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() { @@ -60,8 +55,4 @@ class TestRun { public TestRunCallback getCallback() { return callback; } - - public Set> getExpectedExceptions() { - return expectedExceptions; - } } 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 0b74398ae..250e4b00d 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TestRunner.java +++ b/tools/junit/src/main/java/org/teavm/junit/TestRunner.java @@ -33,10 +33,6 @@ class TestRunner { this.strategy = strategy; } - public int getNumThreads() { - return numThreads; - } - public void setNumThreads(int numThreads) { this.numThreads = numThreads; } @@ -100,32 +96,11 @@ class TestRunner { String status = resultObject.get("status").asText(); switch (status) { case "ok": - if (!run.getExpectedExceptions().isEmpty()) { - run.getCallback().error(new AssertionError("Expected exception was not thrown")); - } else { - run.getCallback().complete(); - } + run.getCallback().complete(); break; case "exception": { String stack = resultObject.get("stack").asText(); 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)); break; }