mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Improving JUnit test runner
This commit is contained in:
parent
2b3cba69bc
commit
d103306c3e
|
@ -20,6 +20,13 @@
|
||||||
<XML>
|
<XML>
|
||||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||||
</XML>
|
</XML>
|
||||||
|
<codeStyleSettings language="HTML">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="JAVA">
|
<codeStyleSettings language="JAVA">
|
||||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
|
<option name="DEFAULT_COMPILER" value="Eclipse" />
|
||||||
<excludeFromCompile>
|
<excludeFromCompile>
|
||||||
<directory url="file://$PROJECT_DIR$/tools/maven/webapp/src/main/resources/archetype-resources" includeSubdirectories="true" />
|
<directory url="file://$PROJECT_DIR$/tools/maven/webapp/src/main/resources/archetype-resources" includeSubdirectories="true" />
|
||||||
</excludeFromCompile>
|
</excludeFromCompile>
|
||||||
|
|
|
@ -71,13 +71,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<skipTests>true</skipTests>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -83,43 +83,6 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.teavm</groupId>
|
|
||||||
<artifactId>teavm-maven-plugin</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>generate-javascript-tests</id>
|
|
||||||
<goals>
|
|
||||||
<goal>testCompile</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<minifying>false</minifying>
|
|
||||||
<scanDependencies>true</scanDependencies>
|
|
||||||
<wildcards>
|
|
||||||
<wildcard>org.teavm.classlib.**.*Test</wildcard>
|
|
||||||
<wildcard>org.teavm.jso.**.*Test</wildcard>
|
|
||||||
<wildcard>org.teavm.platform.metadata.*Test</wildcard>
|
|
||||||
</wildcards>
|
|
||||||
<properties>
|
|
||||||
<java.util.Locale.available>en, en_US, en_GB, ru, ru_RU</java.util.Locale.available>
|
|
||||||
</properties>
|
|
||||||
<incremental>${teavm.test.incremental}</incremental>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>run-javascript-tests</id>
|
|
||||||
<goals>
|
|
||||||
<goal>test</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<skip>${teavm.test.skip}</skip>
|
|
||||||
<numThreads>${teavm.test.threads}</numThreads>
|
|
||||||
<seleniumURL>${teavm.test.selenium}</seleniumURL>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
|
|
@ -23,9 +23,12 @@ import java.text.ParseException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMProperties;
|
||||||
|
import org.teavm.junit.TeaVMProperty;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||||
public class DecimalFormatParseTest {
|
public class DecimalFormatParseTest {
|
||||||
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,12 @@ import java.util.Currency;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMProperties;
|
||||||
|
import org.teavm.junit.TeaVMProperty;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||||
public class DecimalFormatTest {
|
public class DecimalFormatTest {
|
||||||
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Locale;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@ -32,7 +33,7 @@ public class NumberFormatTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@SkipJVM
|
||||||
public void formatsPercent() {
|
public void formatsPercent() {
|
||||||
NumberFormat format = NumberFormat.getPercentInstance(new Locale("en", "US"));
|
NumberFormat format = NumberFormat.getPercentInstance(new Locale("en", "US"));
|
||||||
assertEquals("12,345,679%", format.format(123456.789123));
|
assertEquals("12,345,679%", format.format(123456.789123));
|
||||||
|
|
|
@ -21,9 +21,13 @@ import java.util.Locale;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
|
import org.teavm.junit.TeaVMProperties;
|
||||||
|
import org.teavm.junit.TeaVMProperty;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||||
public class CurrencyTest {
|
public class CurrencyTest {
|
||||||
@Test
|
@Test
|
||||||
public void findsByCode() {
|
public void findsByCode() {
|
||||||
|
@ -46,8 +50,7 @@ public class CurrencyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@SkipJVM
|
||||||
// It seems that JDK can't translate currency names into Russian
|
|
||||||
public void getsDisplayName() {
|
public void getsDisplayName() {
|
||||||
Locale russian = new Locale("ru");
|
Locale russian = new Locale("ru");
|
||||||
Locale english = new Locale("en");
|
Locale english = new Locale("en");
|
||||||
|
@ -64,8 +67,7 @@ public class CurrencyTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@SkipJVM
|
||||||
// It seems that JDK does not know about currency symbols
|
|
||||||
public void getsSymbol() {
|
public void getsSymbol() {
|
||||||
Locale russian = new Locale("ru");
|
Locale russian = new Locale("ru");
|
||||||
Locale english = new Locale("en");
|
Locale english = new Locale("en");
|
||||||
|
|
|
@ -19,9 +19,12 @@ import static org.junit.Assert.*;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMProperties;
|
||||||
|
import org.teavm.junit.TeaVMProperty;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@TeaVMProperties(@TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, en_GB, ru, ru_RU"))
|
||||||
public class LocaleTest {
|
public class LocaleTest {
|
||||||
@Test
|
@Test
|
||||||
public void availableLocalesFound() {
|
public void availableLocalesFound() {
|
||||||
|
|
|
@ -15,14 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.util;
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
|
||||||
public class TestServiceImpl implements TestService {
|
public class TestServiceImpl implements TestService {
|
||||||
private int counter;
|
private int counter;
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,11 @@ import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSMethod;
|
import org.teavm.jso.JSMethod;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
import org.teavm.jso.JSProperty;
|
import org.teavm.jso.JSProperty;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class AnnotationsTest {
|
public class AnnotationsTest {
|
||||||
@Test
|
@Test
|
||||||
public void staticBodyWorks() {
|
public void staticBodyWorks() {
|
||||||
|
|
|
@ -22,9 +22,11 @@ import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
import org.teavm.jso.JSProperty;
|
import org.teavm.jso.JSProperty;
|
||||||
import org.teavm.jso.core.JSString;
|
import org.teavm.jso.core.JSString;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class ConversionTest {
|
public class ConversionTest {
|
||||||
@Test
|
@Test
|
||||||
public void convertsPrimitivesToJavaScript() {
|
public void convertsPrimitivesToJavaScript() {
|
||||||
|
|
|
@ -21,9 +21,11 @@ import org.junit.runner.RunWith;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSFunctor;
|
import org.teavm.jso.JSFunctor;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class FunctorTest {
|
public class FunctorTest {
|
||||||
@Test
|
@Test
|
||||||
public void functorPassed() {
|
public void functorPassed() {
|
||||||
|
|
|
@ -20,13 +20,11 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class ImplementationTest {
|
public class ImplementationTest {
|
||||||
@Test
|
@Test
|
||||||
public void respectsPrecedence() {
|
public void respectsPrecedence() {
|
||||||
|
@ -35,10 +33,10 @@ public class ImplementationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JSBody(params = { "a", "b" }, script = "return a + b;")
|
@JSBody(params = { "a", "b" }, script = "return a + b;")
|
||||||
static final native int add(int a, int b);
|
static native int add(int a, int b);
|
||||||
|
|
||||||
@JSBody(params = { "a", "b" }, script = "return a * b;")
|
@JSBody(params = { "a", "b" }, script = "return a * b;")
|
||||||
static final native int mul(int a, int b);
|
static native int mul(int a, int b);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void inliningUsageCounterWorksProperly() {
|
public void inliningUsageCounterWorksProperly() {
|
||||||
|
|
|
@ -20,9 +20,11 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
import org.teavm.jso.JSObject;
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class JavaInvocationTest {
|
public class JavaInvocationTest {
|
||||||
@Test
|
@Test
|
||||||
public void callStaticMethod() {
|
public void callStaticMethod() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.platform.metadata;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +26,7 @@ import org.teavm.junit.TeaVMTestRunner;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
@RunWith(TeaVMTestRunner.class)
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@SkipJVM
|
||||||
public class MetadataGeneratorTest {
|
public class MetadataGeneratorTest {
|
||||||
@MetadataProvider(TestResourceGenerator.class)
|
@MetadataProvider(TestResourceGenerator.class)
|
||||||
private native TestResource getNull();
|
private native TestResource getNull();
|
||||||
|
|
|
@ -22,17 +22,13 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.diagnostics.Problem;
|
import org.teavm.diagnostics.Problem;
|
||||||
import org.teavm.jso.JSBody;
|
import org.teavm.jso.JSBody;
|
||||||
|
import org.teavm.junit.SkipJVM;
|
||||||
import org.teavm.junit.TeaVMTestRunner;
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.vm.TeaVM;
|
import org.teavm.vm.TeaVM;
|
||||||
import org.teavm.vm.TeaVMBuilder;
|
import org.teavm.vm.TeaVMBuilder;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
@RunWith(TeaVMTestRunner.class)
|
|
||||||
public class JSOTest {
|
public class JSOTest {
|
||||||
@Test
|
@Test
|
||||||
public void reportsAboutWrongParameterOfJSBody() {
|
public void reportsAboutWrongParameterOfJSBody() {
|
||||||
|
|
|
@ -55,7 +55,7 @@ public final class TeaVMProblemRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderCallStack(CallGraph cg, CallLocation location, StringBuilder sb) {
|
public static void renderCallStack(CallGraph cg, CallLocation location, StringBuilder sb) {
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ public final class TeaVMProblemRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderCallLocation(MethodReference method, InstructionLocation location, StringBuilder sb) {
|
public static void renderCallLocation(MethodReference method, InstructionLocation location, StringBuilder sb) {
|
||||||
if (method != null) {
|
if (method != null) {
|
||||||
sb.append(method.getClassName() + "." + method.getName());
|
sb.append(method.getClassName() + "." + method.getName());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
final class ExceptionHelper {
|
||||||
|
private ExceptionHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String showException(Throwable e) {
|
||||||
|
return e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
26
tools/junit/src/main/java/org/teavm/junit/SkipJVM.java
Normal file
26
tools/junit/src/main/java/org/teavm/junit/SkipJVM.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||||
|
public @interface SkipJVM {
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||||
|
public @interface TeaVMProperties {
|
||||||
|
TeaVMProperty[] value();
|
||||||
|
}
|
22
tools/junit/src/main/java/org/teavm/junit/TeaVMProperty.java
Normal file
22
tools/junit/src/main/java/org/teavm/junit/TeaVMProperty.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
public @interface TeaVMProperty {
|
||||||
|
String key();
|
||||||
|
|
||||||
|
String value();
|
||||||
|
}
|
|
@ -16,72 +16,258 @@
|
||||||
package org.teavm.junit;
|
package org.teavm.junit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import org.junit.Test;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.runner.Description;
|
import org.junit.runner.Description;
|
||||||
import org.junit.runner.Runner;
|
|
||||||
import org.junit.runner.notification.Failure;
|
import org.junit.runner.notification.Failure;
|
||||||
import org.junit.runner.notification.RunNotifier;
|
import org.junit.runner.notification.RunNotifier;
|
||||||
|
import org.junit.runners.ParentRunner;
|
||||||
|
import org.junit.runners.model.InitializationError;
|
||||||
|
import org.teavm.callgraph.CallGraph;
|
||||||
|
import org.teavm.diagnostics.DefaultProblemTextConsumer;
|
||||||
|
import org.teavm.diagnostics.Problem;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderSource;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.PreOptimizingClassHolderSource;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.parsing.ClasspathClassHolderSource;
|
||||||
|
import org.teavm.testing.JUnitTestAdapter;
|
||||||
|
import org.teavm.testing.TestAdapter;
|
||||||
|
import org.teavm.tooling.TeaVMProblemRenderer;
|
||||||
import org.teavm.tooling.testing.TeaVMTestTool;
|
import org.teavm.tooling.testing.TeaVMTestTool;
|
||||||
|
import org.teavm.vm.DirectoryBuildTarget;
|
||||||
|
import org.teavm.vm.TeaVM;
|
||||||
|
import org.teavm.vm.TeaVMBuilder;
|
||||||
|
|
||||||
public class TeaVMTestRunner extends Runner {
|
public class TeaVMTestRunner extends ParentRunner<Method> {
|
||||||
private static final String PATH_PARAM = "teavm.junit.target";
|
private static final String PATH_PARAM = "teavm.junit.target";
|
||||||
private Class<?> testClass;
|
private ClassHolder classHolder;
|
||||||
private Description description;
|
private ClassLoader classLoader;
|
||||||
|
private ClassHolderSource classSource;
|
||||||
|
private static Map<ClassLoader, ClassHolderSource> classSources = new WeakHashMap<>();
|
||||||
|
private File outputDir;
|
||||||
|
private TestAdapter testAdapter = new JUnitTestAdapter();
|
||||||
|
private Map<Method, Description> descriptions = new HashMap<>();
|
||||||
|
|
||||||
public TeaVMTestRunner(Class<?> testClass) {
|
public TeaVMTestRunner(Class<?> testClass) throws InitializationError {
|
||||||
this.testClass = testClass;
|
super(testClass);
|
||||||
|
classLoader = TeaVMTestRunner.class.getClassLoader();
|
||||||
|
classSource = getClassSource(classLoader);
|
||||||
|
classHolder = classSource.get(testClass.getName());
|
||||||
|
String outputPath = System.getProperty(PATH_PARAM);
|
||||||
|
if (outputPath != null) {
|
||||||
|
outputDir = new File(outputPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Description getDescription() {
|
protected List<Method> getChildren() {
|
||||||
if (description == null) {
|
List<Method> children = new ArrayList<>();
|
||||||
description = Description.createSuiteDescription(testClass);
|
for (Method method : getTestClass().getJavaClass().getDeclaredMethods()) {
|
||||||
for (Method method : testClass.getMethods()) {
|
MethodHolder methodHolder = classHolder.getMethod(getDescriptor(method));
|
||||||
if (method.getParameterCount() == 0 && method.getReturnType() == void.class
|
if (testAdapter.acceptMethod(methodHolder)) {
|
||||||
&& method.isAnnotationPresent(Test.class)) {
|
children.add(method);
|
||||||
Description testDescription = Description.createTestDescription(testClass, method.getName());
|
|
||||||
description.addChild(testDescription);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return children;
|
||||||
return description;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(RunNotifier notifier) {
|
protected Description describeChild(Method child) {
|
||||||
Description description = getDescription();
|
return descriptions.computeIfAbsent(child, method -> Description.createTestDescription(
|
||||||
|
getTestClass().getJavaClass(), method.getName()));
|
||||||
notifier.fireTestStarted(description);
|
|
||||||
String targetPath = System.getProperty(PATH_PARAM);
|
|
||||||
if (targetPath == null) {
|
|
||||||
for (Description testDescription : description.getChildren()) {
|
|
||||||
notifier.fireTestIgnored(testDescription);
|
|
||||||
}
|
|
||||||
notifier.fireTestIgnored(description);
|
|
||||||
notifier.fireTestFinished(description);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TeaVMTestTool tool = new TeaVMTestTool();
|
@Override
|
||||||
tool.setTargetDirectory(new File(targetPath, testClass.getName()));
|
protected void runChild(Method child, RunNotifier notifier) {
|
||||||
tool.setMinifying(false);
|
notifier.fireTestStarted(describeChild(child));
|
||||||
tool.getTestClasses().add(testClass.getName());
|
|
||||||
|
boolean run = false;
|
||||||
boolean success = true;
|
boolean success = true;
|
||||||
|
if (outputDir != null) {
|
||||||
|
run = true;
|
||||||
|
success &= runInTeaVM(child, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && !child.isAnnotationPresent(SkipJVM.class)
|
||||||
|
&& !child.getDeclaringClass().isAnnotationPresent(SkipJVM.class)) {
|
||||||
|
run = true;
|
||||||
|
success &= runInJvm(child, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!run) {
|
||||||
|
notifier.fireTestIgnored(describeChild(child));
|
||||||
|
}
|
||||||
|
notifier.fireTestFinished(describeChild(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean runInJvm(Method child, RunNotifier notifier) {
|
||||||
|
MethodHolder methodHolder = classHolder.getMethod(getDescriptor(child));
|
||||||
|
Set<Class<?>> expectedExceptions = new HashSet<>();
|
||||||
|
for (String exceptionName : testAdapter.getExpectedExceptions(methodHolder)) {
|
||||||
try {
|
try {
|
||||||
tool.generate();
|
expectedExceptions.add(Class.forName(exceptionName, false, classLoader));
|
||||||
} catch (Exception e) {
|
} catch (ClassNotFoundException e) {
|
||||||
notifier.fireTestFailure(new Failure(description, e));
|
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||||
success = false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
for (Description testDescription : description.getChildren()) {
|
|
||||||
notifier.fireTestStarted(testDescription);
|
|
||||||
notifier.fireTestFinished(testDescription);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier.fireTestFinished(description);
|
Object instance;
|
||||||
|
try {
|
||||||
|
instance = getTestClass().getJavaClass().newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean expectedCaught = false;
|
||||||
|
try {
|
||||||
|
child.invoke(instance);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||||
|
return false;
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
boolean wasExpected = false;
|
||||||
|
for (Class<?> expected : expectedExceptions) {
|
||||||
|
if (expected.isInstance(e.getTargetException())) {
|
||||||
|
expectedCaught = true;
|
||||||
|
wasExpected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!wasExpected) {
|
||||||
|
notifier.fireTestFailure(new Failure(describeChild(child), e.getTargetException()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expectedCaught && !expectedExceptions.isEmpty()) {
|
||||||
|
notifier.fireTestAssumptionFailed(new Failure(describeChild(child),
|
||||||
|
new AssertionError("Expected exception was not thrown")));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean runInTeaVM(Method child, RunNotifier notifier) {
|
||||||
|
CompileResult compileResult;
|
||||||
|
try {
|
||||||
|
compileResult = compileTest(child);
|
||||||
|
} catch (IOException e) {
|
||||||
|
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compileResult.success) {
|
||||||
|
notifier.fireTestFailure(new Failure(describeChild(child),
|
||||||
|
new AssertionError(compileResult.errorMessage)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompileResult compileTest(Method method) throws IOException {
|
||||||
|
CompileResult result = new CompileResult();
|
||||||
|
|
||||||
|
File path = outputDir;
|
||||||
|
path = new File(path, method.getDeclaringClass().getName().replace('.', '/'));
|
||||||
|
path = new File(path, method.getName());
|
||||||
|
path.mkdirs();
|
||||||
|
File outputFile = new File(path, "test.js");
|
||||||
|
result.file = outputFile;
|
||||||
|
|
||||||
|
resourceToFile("org/teavm/javascript/runtime.js", new File(path, "runtime.js"));
|
||||||
|
resourceToFile("teavm-run-test.html", new File(path, "run-test.html"));
|
||||||
|
|
||||||
|
ClassLoader classLoader = TeaVMTestRunner.class.getClassLoader();
|
||||||
|
ClassHolderSource classSource = getClassSource(classLoader);
|
||||||
|
|
||||||
|
MethodHolder methodHolder = classHolder.getMethod(getDescriptor(method));
|
||||||
|
Class<?> runnerType = testAdapter.getRunner(methodHolder);
|
||||||
|
|
||||||
|
TeaVM vm = new TeaVMBuilder()
|
||||||
|
.setClassLoader(classLoader)
|
||||||
|
.setClassSource(classSource)
|
||||||
|
.build();
|
||||||
|
vm.setIncremental(false);
|
||||||
|
vm.setMinifying(false);
|
||||||
|
vm.installPlugins();
|
||||||
|
|
||||||
|
new TestExceptionPlugin().install(vm);
|
||||||
|
new TestEntryPointTransformer(runnerType.getName(), methodHolder.getReference()).install(vm);
|
||||||
|
|
||||||
|
try (Writer innerWriter = new OutputStreamWriter(new FileOutputStream(outputFile), "UTF-8")) {
|
||||||
|
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
|
||||||
|
Throwable.class, String.class);
|
||||||
|
vm.entryPoint("runTest", new MethodReference(TestEntryPoint.class, "run", void.class)).async();
|
||||||
|
vm.entryPoint("extractException", exceptionMsg);
|
||||||
|
vm.build(innerWriter, new DirectoryBuildTarget(outputDir));
|
||||||
|
if (!vm.getProblemProvider().getProblems().isEmpty()) {
|
||||||
|
result.success = false;
|
||||||
|
result.errorMessage = buildErrorMessage(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodDescriptor getDescriptor(Method method) {
|
||||||
|
ValueType[] signature = Stream.concat(Arrays.stream(method.getParameterTypes()).map(ValueType::parse),
|
||||||
|
Stream.of(ValueType.parse(method.getReturnType())))
|
||||||
|
.toArray(ValueType[]::new);
|
||||||
|
return new MethodDescriptor(method.getName(), signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildErrorMessage(TeaVM vm) {
|
||||||
|
CallGraph cg = vm.getDependencyInfo().getCallGraph();
|
||||||
|
DefaultProblemTextConsumer consumer = new DefaultProblemTextConsumer();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Problem problem : vm.getProblemProvider().getProblems()) {
|
||||||
|
consumer.clear();
|
||||||
|
problem.render(consumer);
|
||||||
|
sb.append(consumer.getText());
|
||||||
|
TeaVMProblemRenderer.renderCallStack(cg, problem.getLocation(), sb);
|
||||||
|
sb.append("\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resourceToFile(String resource, File fileName) throws IOException {
|
||||||
|
try (InputStream input = TeaVMTestTool.class.getClassLoader().getResourceAsStream(resource);
|
||||||
|
OutputStream output = new FileOutputStream(fileName)) {
|
||||||
|
IOUtils.copy(input, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassHolderSource getClassSource(ClassLoader classLoader) {
|
||||||
|
return classSources.computeIfAbsent(classLoader, cl -> new PreOptimizingClassHolderSource(
|
||||||
|
new ClasspathClassHolderSource(classLoader)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CompileResult {
|
||||||
|
boolean success = true;
|
||||||
|
String errorMessage;
|
||||||
|
File file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import org.teavm.testing.TestRunner;
|
||||||
|
|
||||||
|
final class TestEntryPoint {
|
||||||
|
private static Object testCase;
|
||||||
|
|
||||||
|
private TestEntryPoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void run() throws Throwable {
|
||||||
|
createRunner().run(() -> launchTest());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native TestRunner createRunner();
|
||||||
|
|
||||||
|
private static native void launchTest();
|
||||||
|
|
||||||
|
private static native boolean isExpectedException(Class<?> cls);
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
|
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.MethodReference;
|
||||||
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
|
import org.teavm.vm.spi.TeaVMHost;
|
||||||
|
import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
|
|
||||||
|
class TestEntryPointTransformer implements ClassHolderTransformer, TeaVMPlugin {
|
||||||
|
private String runnerClassName;
|
||||||
|
private MethodReference testMethod;
|
||||||
|
|
||||||
|
public TestEntryPointTransformer(String runnerClassName, MethodReference testMethod) {
|
||||||
|
this.runnerClassName = runnerClassName;
|
||||||
|
this.testMethod = testMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void install(TeaVMHost host) {
|
||||||
|
host.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||||
|
if (cls.getName().equals(TestEntryPoint.class.getName())) {
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
if (method.getName().equals("createRunner")) {
|
||||||
|
method.setProgram(generateRunnerProgram(method, innerSource));
|
||||||
|
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||||
|
} else if (method.getName().equals("launchTest")) {
|
||||||
|
method.setProgram(generateLaunchProgram(method, innerSource));
|
||||||
|
method.getModifiers().remove(ElementModifier.NATIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Program generateRunnerProgram(MethodHolder method, ClassReaderSource innerSource) {
|
||||||
|
ProgramEmitter pe = ProgramEmitter.create(method, innerSource);
|
||||||
|
pe.construct(runnerClassName).returnValue();
|
||||||
|
return pe.getProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Program generateLaunchProgram(MethodHolder method, ClassReaderSource innerSource) {
|
||||||
|
ProgramEmitter pe = ProgramEmitter.create(method, innerSource);
|
||||||
|
ValueEmitter testCaseVar = pe.getField(TestEntryPoint.class, "testCase", Object.class);
|
||||||
|
pe.when(testCaseVar.isNull())
|
||||||
|
.thenDo(() -> {
|
||||||
|
pe.setField(TestEntryPoint.class, "testCase",
|
||||||
|
pe.construct(testMethod.getClassName()).cast(Object.class));
|
||||||
|
});
|
||||||
|
pe.getField(TestEntryPoint.class, "testCase", Object.class)
|
||||||
|
.cast(ValueType.object(testMethod.getClassName()))
|
||||||
|
.invokeSpecial(testMethod);
|
||||||
|
pe.exit();
|
||||||
|
return pe.getProgram();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import org.teavm.dependency.AbstractDependencyListener;
|
||||||
|
import org.teavm.dependency.DependencyAgent;
|
||||||
|
import org.teavm.dependency.DependencyNode;
|
||||||
|
import org.teavm.dependency.MethodDependency;
|
||||||
|
import org.teavm.model.CallLocation;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
class TestExceptionDependency extends AbstractDependencyListener {
|
||||||
|
private MethodReference getMessageRef = new MethodReference(ExceptionHelper.class, "showException",
|
||||||
|
Throwable.class, String.class);
|
||||||
|
private DependencyNode allClasses;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void started(DependencyAgent agent) {
|
||||||
|
allClasses = agent.createNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void classReached(DependencyAgent agent, String className, CallLocation location) {
|
||||||
|
if (isException(agent.getClassSource(), className)) {
|
||||||
|
allClasses.propagate(agent.getType(className));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isException(ClassReaderSource classSource, String className) {
|
||||||
|
while (className != null) {
|
||||||
|
if (className.equals("java.lang.Throwable")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ClassReader cls = classSource.get(className);
|
||||||
|
if (cls == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
className = cls.getParent();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||||
|
if (method.getReference().equals(getMessageRef)) {
|
||||||
|
allClasses.connect(method.getVariable(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 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.junit;
|
||||||
|
|
||||||
|
import org.teavm.vm.spi.TeaVMHost;
|
||||||
|
import org.teavm.vm.spi.TeaVMPlugin;
|
||||||
|
|
||||||
|
class TestExceptionPlugin implements TeaVMPlugin {
|
||||||
|
@Override
|
||||||
|
public void install(TeaVMHost host) {
|
||||||
|
host.add(new TestExceptionDependency());
|
||||||
|
}
|
||||||
|
}
|
53
tools/junit/src/main/resources/teavm-run-test.html
Normal file
53
tools/junit/src/main/resources/teavm-run-test.html
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>TeaVM JUnit test</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" src="runtime.js"></script>
|
||||||
|
<script type="text/javascript" src="test.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
$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 = buildErrorMessage(e);
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
if (thread.isSuspending()) {
|
||||||
|
thread.push(instance);
|
||||||
|
thread.push(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message = "OK";
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.body.appendChild(document.createTextNode(message));
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildErrorMessage(e) {
|
||||||
|
var stack = e.stack;
|
||||||
|
if (e.$javaException && e.$javaException.constructor.$meta) {
|
||||||
|
stack = e.$javaException.constructor.$meta.name + ": ";
|
||||||
|
var exceptionMessage = extractException(e.$javaException);
|
||||||
|
stack += exceptionMessage ? $rt_ustr(exceptionMessage) : "";
|
||||||
|
}
|
||||||
|
stack += "\n" + stack;
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user