Fix generation of variable names in minified mode (fix #227). JUnit runner can be configured to run tests in minified and optimized modes. Apply these modes to travis config.

This commit is contained in:
Alexey Andreev 2016-11-04 13:21:01 +03:00
parent 1335476abe
commit 2a3b0cd597
5 changed files with 139 additions and 20 deletions

View File

@ -13,7 +13,7 @@
<option name="MAIN_CLASS_NAME" value="" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" /> <option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" /> <option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -Dteavm.junit.target=target/js-tests -Dteavm.junit.js.runner=htmlunit -Dteavm.junit.js.threads=2" /> <option name="VM_PARAMETERS" value="-ea -Dteavm.junit.target=target/js-tests -Dteavm.junit.js.runner=htmlunit -Dteavm.junit.js.threads=1 -Dteavm.junit.minified=true -Dteavm.junit.optimized=true" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$MODULE_DIR$" /> <option name="WORKING_DIRECTORY" value="file://$MODULE_DIR$" />
<option name="ENV_VARIABLES" /> <option name="ENV_VARIABLES" />
@ -22,7 +22,7 @@
<value defaultName="singleModule" /> <value defaultName="singleModule" />
</option> </option>
<envs /> <envs />
<dir value="$PROJECT_DIR$/../../idea-debug/teavm/tests/src/test/java" /> <dir value="$USER_HOME$/idea-debug/teavm/tests/src/test/java" />
<patterns /> <patterns />
<method /> <method />
</configuration> </configuration>

View File

@ -14,6 +14,8 @@ script: >
mvn -e test \ mvn -e test \
-Dteavm.junit.target=target/js-tests \ -Dteavm.junit.target=target/js-tests \
-Dteavm.junit.js.runner=htmlunit \ -Dteavm.junit.js.runner=htmlunit \
-Dteavm.junit.js.threads=1 -Dteavm.junit.js.threads=1 \
-Dteavm.junit.optimized=true \
-Dteavm.junit.minified=true
after_script: after_script:
- rm -rf $HOME/.m2/repository/org/teavm - rm -rf $HOME/.m2/repository/org/teavm

View File

@ -16,8 +16,8 @@
package org.teavm.backend.javascript.rendering; package org.teavm.backend.javascript.rendering;
public final class RenderingUtil { public final class RenderingUtil {
public static final String variableNames = "abcdefghijkmnopqrstuvwxyz"; private static final String variableNames = "abcdefghijkmnopqrstuvwxyz";
public static final String variablePartNames = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static final String variablePartNames = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private RenderingUtil() { private RenderingUtil() {
} }
@ -75,10 +75,11 @@ public final class RenderingUtil {
public static String indexToId(int index) { public static String indexToId(int index) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
do { sb.append(variableNames.charAt(index % variableNames.length()));
while (index > 0) {
sb.append(variablePartNames.charAt(index % variablePartNames.length())); sb.append(variablePartNames.charAt(index % variablePartNames.length()));
index /= variablePartNames.length(); index /= variablePartNames.length();
} while (index > 0); }
return sb.toString(); return sb.toString();
} }
} }

View File

@ -0,0 +1,79 @@
/*
* 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.backend.javascript.JavaScriptTarget;
import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMOptimizationLevel;
interface TeaVMTestConfiguration {
String getSuffix();
void apply(TeaVM vm);
void apply(JavaScriptTarget target);
TeaVMTestConfiguration DEFAULT = new TeaVMTestConfiguration() {
@Override
public String getSuffix() {
return "";
}
@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
}
@Override
public void apply(JavaScriptTarget target) {
target.setMinifying(false);
}
};
TeaVMTestConfiguration OPTIMIZED = new TeaVMTestConfiguration() {
@Override
public String getSuffix() {
return "optimized";
}
@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
}
@Override
public void apply(JavaScriptTarget target) {
target.setMinifying(false);
}
};
TeaVMTestConfiguration MINIFIED = new TeaVMTestConfiguration() {
@Override
public String getSuffix() {
return "min";
}
@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
}
@Override
public void apply(JavaScriptTarget target) {
target.setMinifying(true);
}
};
}

View File

@ -37,6 +37,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.junit.runner.Description; import org.junit.runner.Description;
@ -199,7 +200,21 @@ public class TeaVMTestRunner extends Runner {
} }
if (success && outputDir != null) { if (success && outputDir != null) {
runInTeaVM(child, notifier, expectedExceptions); Description description = describeChild(child);
List<TeaVMTestConfiguration> configurations = getConfigurations();
int[] configurationIndex = new int[] { 0 };
List<Consumer<Boolean>> onSuccess = new ArrayList<>();
onSuccess.add(runSuccess -> {
if (runSuccess && configurationIndex[0] < configurations.size()) {
runInTeaVM(child, notifier, expectedExceptions, configurations.get(configurationIndex[0]++),
onSuccess.get(0));
} else {
notifier.fireTestFinished(description);
latch.countDown();
}
});
onSuccess.get(0).accept(true);
} else { } else {
if (!run) { if (!run) {
notifier.fireTestIgnored(describeChild(child)); notifier.fireTestIgnored(describeChild(child));
@ -247,41 +262,41 @@ public class TeaVMTestRunner extends Runner {
return true; return true;
} }
private boolean runInTeaVM(Method child, RunNotifier notifier, Set<Class<?>> expectedExceptions) { private boolean runInTeaVM(Method child, RunNotifier notifier, Set<Class<?>> expectedExceptions,
TeaVMTestConfiguration configuration, Consumer<Boolean> onComplete) {
Description description = describeChild(child); Description description = describeChild(child);
CompileResult compileResult; CompileResult compileResult;
try { try {
compileResult = compileTest(child); compileResult = compileTest(child, configuration);
} catch (IOException e) { } catch (Exception e) {
notifier.fireTestFailure(new Failure(description, e)); notifier.fireTestFailure(new Failure(description, e));
onComplete.accept(false);
return false; return false;
} }
if (!compileResult.success) { if (!compileResult.success) {
notifier.fireTestFailure(new Failure(description, notifier.fireTestFailure(new Failure(description,
new AssertionError(compileResult.errorMessage))); new AssertionError(compileResult.errorMessage)));
notifier.fireTestFinished(description); onComplete.accept(false);
latch.countDown();
return false; return false;
} }
if (runStrategy == null) { if (runStrategy == null) {
notifier.fireTestFinished(description); onComplete.accept(true);
latch.countDown();
return true; return true;
} }
TestRunCallback callback = new TestRunCallback() { TestRunCallback callback = new TestRunCallback() {
@Override @Override
public void complete() { public void complete() {
notifier.fireTestFinished(description); onComplete.accept(true);
latch.countDown();
} }
@Override @Override
public void error(Throwable e) { public void error(Throwable e) {
notifier.fireTestFailure(new Failure(description, e)); notifier.fireTestFailure(new Failure(description, e));
onComplete.accept(false);
} }
}; };
@ -325,14 +340,22 @@ public class TeaVMTestRunner extends Runner {
} }
} }
private CompileResult compileTest(Method method) throws IOException { private CompileResult compileTest(Method method, TeaVMTestConfiguration configuration) throws IOException {
CompileResult result = new CompileResult(); CompileResult result = new CompileResult();
File path = outputDir; File path = outputDir;
path = new File(path, method.getDeclaringClass().getName().replace('.', '/')); path = new File(path, method.getDeclaringClass().getName().replace('.', '/'));
path = new File(path, method.getName()); path = new File(path, method.getName());
path.mkdirs(); path.mkdirs();
File outputFile = new File(path, "test.js");
StringBuilder simpleName = new StringBuilder();
simpleName.append("test");
String suffix = configuration.getSuffix();
if (!suffix.isEmpty()) {
simpleName.append('-').append(suffix);
}
simpleName.append(".js");
File outputFile = new File(path, simpleName.toString());
result.file = outputFile; result.file = outputFile;
resourceToFile("org/teavm/backend/javascript/runtime.js", new File(path, "runtime.js")); resourceToFile("org/teavm/backend/javascript/runtime.js", new File(path, "runtime.js"));
@ -345,12 +368,14 @@ public class TeaVMTestRunner extends Runner {
Class<?> runnerType = testAdapter.getRunner(methodHolder); Class<?> runnerType = testAdapter.getRunner(methodHolder);
JavaScriptTarget jsTarget = new JavaScriptTarget(); JavaScriptTarget jsTarget = new JavaScriptTarget();
jsTarget.setMinifying(false); configuration.apply(jsTarget);
TeaVM vm = new TeaVMBuilder(jsTarget) TeaVM vm = new TeaVMBuilder(jsTarget)
.setClassLoader(classLoader) .setClassLoader(classLoader)
.setClassSource(classSource) .setClassSource(classSource)
.build(); .build();
vm.setIncremental(false); vm.setIncremental(false);
configuration.apply(vm);
vm.installPlugins(); vm.installPlugins();
new TestExceptionPlugin().install(vm); new TestExceptionPlugin().install(vm);
@ -373,6 +398,18 @@ public class TeaVMTestRunner extends Runner {
return result; return result;
} }
private List<TeaVMTestConfiguration> getConfigurations() {
List<TeaVMTestConfiguration> configurations = new ArrayList<>();
configurations.add(TeaVMTestConfiguration.DEFAULT);
if (Boolean.parseBoolean(System.getProperty("teavm.junit.minified", "false"))) {
configurations.add(TeaVMTestConfiguration.MINIFIED);
}
if (Boolean.parseBoolean(System.getProperty("teavm.junit.optimized", "false"))) {
configurations.add(TeaVMTestConfiguration.OPTIMIZED);
}
return configurations;
}
private void applyProperties(Class<?> cls, Properties result) { private void applyProperties(Class<?> cls, Properties result) {
if (cls.getSuperclass() != null) { if (cls.getSuperclass() != null) {
applyProperties(cls.getSuperclass(), result); applyProperties(cls.getSuperclass(), result);