diff --git a/core/pom.xml b/core/pom.xml
index 798a6b5a8..98b1d0192 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -45,6 +45,11 @@
hppc
0.6.1
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ true
+
TeaVM core
diff --git a/core/src/main/java/org/teavm/model/MethodReference.java b/core/src/main/java/org/teavm/model/MethodReference.java
index a60d8b4ea..d5ed4a70f 100644
--- a/core/src/main/java/org/teavm/model/MethodReference.java
+++ b/core/src/main/java/org/teavm/model/MethodReference.java
@@ -15,6 +15,8 @@
*/
package org.teavm.model;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
import java.util.Arrays;
/**
@@ -132,6 +134,7 @@ public class MethodReference {
}
@Override
+ @JsonValue
public String toString() {
if (reprCache == null) {
reprCache = className + "." + name + signatureToString();
@@ -139,6 +142,7 @@ public class MethodReference {
return reprCache;
}
+ @JsonCreator
public static MethodReference parse(String string) {
MethodReference reference = parseIfPossible(string);
if (reference == null) {
diff --git a/samples/pom.xml b/samples/pom.xml
index 60292acad..fea836574 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -36,8 +36,6 @@
video
async
kotlin
-
\ No newline at end of file
diff --git a/tests/pom.xml b/tests/pom.xml
index 28955d1bd..17b57350d 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -27,6 +27,12 @@
TeaVM tests
Project containing TeaVM tests, as it is impossible to test each module separately
+
+ false
+ 1
+
+
+
org.teavm
@@ -93,6 +99,10 @@
test
+
+ ${teavm.test.threads}
+ ${teavm.test.selenium}
+
diff --git a/tools/core/pom.xml b/tools/core/pom.xml
index 7abaacfc8..54c00a376 100644
--- a/tools/core/pom.xml
+++ b/tools/core/pom.xml
@@ -24,6 +24,7 @@
../..
teavm-tooling
+ bundle
TeaVM tooling core
TeaVM API that helps to create tooling
@@ -59,6 +60,17 @@
org.apache.maven.plugins
maven-javadoc-plugin
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ org.teavm.*
+ teavm-tooling
+
+
+
\ No newline at end of file
diff --git a/tools/eclipse/core-plugin/META-INF/MANIFEST.MF b/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
index a0133cc02..b4bee0aa9 100644
--- a/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/core-plugin/META-INF/MANIFEST.MF
@@ -71,5 +71,6 @@ Export-Package: org.teavm.cache,
org.teavm.resource,
org.teavm.testing,
org.teavm.tooling,
+ org.teavm.tooling.sources,
org.teavm.vm,
org.teavm.vm.spi
diff --git a/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF b/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
index 062e541a9..1574d6301 100644
--- a/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/m2e-plugin/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: TeaVM plugin for m2e
Bundle-SymbolicName: teavm-eclipse-m2e-plugin;singleton:=true
Bundle-Version: 0.4.0.qualifier
Bundle-Vendor: Alexey Andreev
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: teavm-eclipse-plugin;bundle-version="[0.4.0,0.5.0)",
org.eclipse.m2e.core;bundle-version="[1.3,2)",
org.eclipse.core.runtime;bundle-version="[3.8,4.0)",
diff --git a/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml b/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
index 3ca52caff..e2fb85a6e 100644
--- a/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
+++ b/tools/eclipse/m2e-plugin/lifecycle-mapping-metadata.xml
@@ -7,7 +7,7 @@
teavm-maven-plugin
0.4.0-SNAPSHOT
- build-javascript
+ compile
diff --git a/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java b/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
index 220d4ed0f..a8ad00c3a 100644
--- a/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
+++ b/tools/eclipse/m2e-plugin/src/main/java/org/teavm/eclipse/m2e/TeaVMProjectConfigurator.java
@@ -33,7 +33,7 @@ public class TeaVMProjectConfigurator extends AbstractProjectConfigurator {
private static final String TOOL_ID = "teavm-eclipse-m2e-plugin.tool";
private static final String TEAVM_ARTIFACT_ID = "teavm-maven-plugin";
private static final String TEAVM_GROUP_ID = "org.teavm";
- private static final String TEAVM_MAIN_GOAL = "build-javascript";
+ private static final String TEAVM_MAIN_GOAL = "compile";
private int executionIdGenerator;
private Set usedExecutionIds = new HashSet<>();
private IMaven maven;
diff --git a/tools/eclipse/plugin/META-INF/MANIFEST.MF b/tools/eclipse/plugin/META-INF/MANIFEST.MF
index 416ca1e23..4a219dbb4 100644
--- a/tools/eclipse/plugin/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugin/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: TeaVM plugin for Eclipse
Bundle-SymbolicName: teavm-eclipse-plugin;singleton:=true
Bundle-Version: 0.4.0.qualifier
Bundle-Vendor: Alexey Andreev
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Activator: org.teavm.eclipse.TeaVMEclipsePlugin
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.8.0,4.0)",
org.eclipse.debug.core;bundle-version="[3.7.0,4.0)",
@@ -48,5 +48,6 @@ Import-Package: org.teavm.cache,
org.teavm.resource,
org.teavm.testing,
org.teavm.tooling,
+ org.teavm.tooling.sources,
org.teavm.vm,
org.teavm.vm.spi
diff --git a/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java b/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
index 41c2184b7..a09363e27 100644
--- a/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
+++ b/tools/eclipse/plugin/src/main/java/org/teavm/eclipse/TeaVMProjectBuilder.java
@@ -21,22 +21,62 @@ import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.util.*;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
-import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.Signature;
import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite;
import org.teavm.diagnostics.Problem;
import org.teavm.diagnostics.ProblemTextConsumer;
-import org.teavm.model.*;
-import org.teavm.tooling.*;
+import org.teavm.model.CallLocation;
+import org.teavm.model.ClassHolderTransformer;
+import org.teavm.model.FieldReference;
+import org.teavm.model.InstructionLocation;
+import org.teavm.model.MethodReference;
+import org.teavm.model.ValueType;
+import org.teavm.tooling.ClassAlias;
+import org.teavm.tooling.RuntimeCopyOperation;
+import org.teavm.tooling.TeaVMTool;
+import org.teavm.tooling.TeaVMToolException;
+import org.teavm.tooling.sources.DirectorySourceFileProvider;
+import org.teavm.tooling.sources.JarSourceFileProvider;
+import org.teavm.tooling.sources.SourceFileProvider;
/**
*
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
index de0617ebd..5beb6c135 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/BuildJavascriptTestMojo.java
@@ -28,7 +28,6 @@ import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
-import java.util.Properties;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -82,12 +81,6 @@ public class BuildJavascriptTestMojo extends AbstractJavascriptMojo {
@Parameter
private String[] additionalScripts;
- @Parameter
- private Properties properties;
-
- @Parameter
- private boolean incremental;
-
private TeaVMTestTool tool = new TeaVMTestTool();
@Override
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
index f89a3d176..8bfd3857e 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/RunTestsMojo.java
@@ -16,13 +16,17 @@
package org.teavm.maven;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.Reader;
+import java.io.Writer;
+import java.net.MalformedURLException;
import java.net.URL;
-import java.util.List;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -40,15 +44,37 @@ public class RunTestsMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.build.directory}/javascript-test")
private File testDirectory;
+ @Parameter(defaultValue = "${project.build.directory}/teavm-test-report.json")
+ private File reportFile;
+
@Parameter
- private URL seleniumURL;
+ private String seleniumURL;
+
+ @Parameter
+ private int numThreads = 1;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
+ if (seleniumURL == null || seleniumURL.isEmpty()) {
+ getLog().info("Tests build skipped as selenium URL was not specified");
+ return;
+ }
+
+ if (System.getProperty("maven.test.skip", "false").equals("true") ||
+ System.getProperty("skipTests") != null) {
+ getLog().info("Tests build skipped as specified by system property");
+ return;
+ }
+
SeleniumTestRunner runner = new SeleniumTestRunner();
runner.setLog(getLog());
runner.setDirectory(testDirectory);
- runner.setUrl(seleniumURL);
+ runner.setNumThreads(numThreads);
+ try {
+ runner.setUrl(new URL(seleniumURL));
+ } catch (MalformedURLException e) {
+ throw new MojoFailureException("Can't parse URL: " + seleniumURL, e);
+ }
TestPlan plan;
ObjectMapper mapper = new ObjectMapper();
@@ -63,23 +89,31 @@ public class RunTestsMojo extends AbstractMojo {
processReport(runner.getReport());
}
- private void processReport(List report) throws MojoExecutionException {
- if (report.isEmpty()) {
+ private void processReport(TestReport report) throws MojoExecutionException, MojoFailureException {
+ if (report.getResults().isEmpty()) {
getLog().info("No tests ran");
return;
}
int failedTests = 0;
- for (TestResult result : report) {
+ for (TestResult result : report.getResults()) {
if (result.getStatus() != TestStatus.PASSED) {
failedTests++;
}
}
if (failedTests > 0) {
- throw new MojoExecutionException(failedTests + " of " + report.size() + " test(s) failed");
+ throw new MojoExecutionException(failedTests + " of " + report.getResults().size() + " test(s) failed");
} else {
- getLog().info("All of " + report.size() + " tests successfully passed");
+ getLog().info("All of " + report.getResults().size() + " tests successfully passed");
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(reportFile), "UTF-8")) {
+ mapper.writeValue(writer, report);
+ } catch (IOException e) {
+ throw new MojoFailureException("Error writing test report", e);
}
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
index 836cfd405..b90e7da2c 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/SeleniumTestRunner.java
@@ -34,7 +34,8 @@ import org.apache.maven.plugin.logging.Log;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
-import org.openqa.selenium.chrome.ChromeDriver;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.remote.RemoteWebDriver;
import org.teavm.model.MethodReference;
import org.teavm.tooling.testing.TestCase;
import org.teavm.tooling.testing.TestGroup;
@@ -99,7 +100,7 @@ public class SeleniumTestRunner {
latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; ++i) {
new Thread(() -> {
- ChromeDriver driver = new ChromeDriver();
+ RemoteWebDriver driver = new RemoteWebDriver(DesiredCapabilities.chrome());
webDriver.set(driver);
localReport.set(new ArrayList<>());
while (!seleniumStopped || !seleniumTaskQueue.isEmpty()) {
@@ -157,13 +158,24 @@ public class SeleniumTestRunner {
MethodReference ref = MethodReference.parse(testCase.getTestMethod());
switch (status) {
case "ok":
- log.info("Test passed: " + testCase.getTestMethod());
- localReport.get().add(TestResult.passed(ref));
+ if (testCase.getExpectedExceptions().isEmpty()) {
+ log.info("Test passed: " + testCase.getTestMethod());
+ localReport.get().add(TestResult.passed(ref));
+ } else {
+ log.info("Test failed: " + testCase.getTestMethod());
+ localReport.get().add(TestResult.exceptionNotThrown(ref));
+ }
break;
case "exception": {
String stack = resultObject.get("stack").asText();
- log.info("Test failed: " + testCase.getTestMethod());
- localReport.get().add(TestResult.error(ref, stack));
+ String exception = resultObject.get("exception").asText();
+ if (!testCase.getExpectedExceptions().contains(exception)) {
+ log.info("Test failed: " + testCase.getTestMethod());
+ localReport.get().add(TestResult.error(ref, exception, stack));
+ } else {
+ log.info("Test passed: " + testCase.getTestMethod());
+ localReport.get().add(TestResult.passed(ref));
+ }
break;
}
}
@@ -194,7 +206,9 @@ public class SeleniumTestRunner {
}
}
- public List getReport() {
- return new ArrayList<>(report);
+ public TestReport getReport() {
+ TestReport report = new TestReport();
+ report.getResults().addAll(this.report);
+ return report;
}
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TestReport.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TestReport.java
new file mode 100644
index 000000000..d8fab47b1
--- /dev/null
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TestReport.java
@@ -0,0 +1,16 @@
+package org.teavm.maven;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class TestReport {
+ private List results = new ArrayList<>();
+
+ public List getResults() {
+ return results;
+ }
+}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TestResult.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TestResult.java
index 1151f2c85..9728857e6 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/TestResult.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TestResult.java
@@ -15,6 +15,11 @@
*/
package org.teavm.maven;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
import org.teavm.model.MethodReference;
/**
@@ -24,30 +29,49 @@ import org.teavm.model.MethodReference;
public class TestResult {
private MethodReference method;
private TestStatus status;
+ private String exception;
private String stack;
- private TestResult(MethodReference method, TestStatus status, String stack) {
+ @JsonCreator
+ TestResult(
+ @JsonProperty("method") MethodReference method,
+ @JsonProperty("status") TestStatus status,
+ @JsonInclude(Include.NON_NULL) @JsonProperty("exception") String exception,
+ @JsonInclude(Include.NON_NULL) @JsonProperty("stack") String stack) {
this.method = method;
this.status = status;
+ this.exception = exception;
this.stack = stack;
}
public static TestResult passed(MethodReference method) {
- return new TestResult(method, TestStatus.PASSED, null);
+ return new TestResult(method, TestStatus.PASSED, null, null);
}
- public static TestResult error(MethodReference method, String stack) {
- return new TestResult(method, TestStatus.ERROR, stack);
+ public static TestResult exceptionNotThrown(MethodReference method) {
+ return new TestResult(method, TestStatus.EXCEPTION_NOT_THROWN, null, null);
}
+ public static TestResult error(MethodReference method, String exception, String stack) {
+ return new TestResult(method, TestStatus.ERROR, exception, stack);
+ }
+
+ @JsonGetter
public MethodReference getMethod() {
return method;
}
+ @JsonGetter
public TestStatus getStatus() {
return status;
}
+ @JsonGetter
+ public String getException() {
+ return exception;
+ }
+
+ @JsonGetter
public String getStack() {
return stack;
}
diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TestStatus.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TestStatus.java
index 8bdbaecd2..366859a58 100644
--- a/tools/maven/plugin/src/main/java/org/teavm/maven/TestStatus.java
+++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TestStatus.java
@@ -21,5 +21,6 @@ package org.teavm.maven;
*/
public enum TestStatus {
PASSED,
- ERROR
+ ERROR,
+ EXCEPTION_NOT_THROWN
}
diff --git a/tools/maven/webapp/src/main/resources/archetype-resources/pom.xml b/tools/maven/webapp/src/main/resources/archetype-resources/pom.xml
index 0a265a56c..5a2eebaa2 100644
--- a/tools/maven/webapp/src/main/resources/archetype-resources/pom.xml
+++ b/tools/maven/webapp/src/main/resources/archetype-resources/pom.xml
@@ -8,7 +8,7 @@
war
- 1.7
+ 1.8
0.4.0-SNAPSHOT
UTF-8
@@ -25,15 +25,7 @@
org.teavm
- teavm-jso
- ${teavm.version}
- provided
-
-
-
-
- org.teavm
- teavm-dom
+ teavm-jso-apis
${teavm.version}
provided
@@ -80,9 +72,8 @@
web-client
- prepare-package
- build-javascript
+ compile
${package}.Client
-
- SEPARATE
-
true