mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
Wasm: support running WASI tests in JUnit
This commit is contained in:
parent
8f4e4e811f
commit
bb087b7630
@ -18,5 +18,6 @@ package org.teavm.junit;
|
||||
enum RunKind {
|
||||
JAVASCRIPT,
|
||||
C,
|
||||
WASM
|
||||
WASM,
|
||||
WASI
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ import org.junit.runners.model.InitializationError;
|
||||
import org.teavm.backend.c.CTarget;
|
||||
import org.teavm.backend.c.generate.CNameProvider;
|
||||
import org.teavm.backend.javascript.JavaScriptTarget;
|
||||
import org.teavm.backend.wasm.WasmRuntimeType;
|
||||
import org.teavm.backend.wasm.WasmTarget;
|
||||
import org.teavm.callgraph.CallGraph;
|
||||
import org.teavm.debugging.information.DebugInformation;
|
||||
@ -110,6 +111,8 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
static final String JS_DECODE_STACK = "teavm.junit.js.decodeStack";
|
||||
private static final String C_ENABLED = "teavm.junit.c";
|
||||
private static final String WASM_ENABLED = "teavm.junit.wasm";
|
||||
private static final String WASI_ENABLED = "teavm.junit.wasi";
|
||||
private static final String WASI_RUNNER = "teavm.junit.wasi.runner";
|
||||
private static final String C_COMPILER = "teavm.junit.c.compiler";
|
||||
private static final String C_LINE_NUMBERS = "teavm.junit.c.lineNumbers";
|
||||
private static final String MINIFIED = "teavm.junit.minified";
|
||||
@ -192,6 +195,10 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
if (cCommand != null) {
|
||||
runners.get(RunKind.C).strategy = new CRunStrategy(cCommand);
|
||||
}
|
||||
String wasiCommand = System.getProperty(WASI_RUNNER);
|
||||
if (wasiCommand != null) {
|
||||
runners.get(RunKind.WASI).strategy = new WasiRunStrategy(wasiCommand);
|
||||
}
|
||||
|
||||
runStrategyName = System.getProperty(WASM_RUNNER);
|
||||
if (runStrategyName != null) {
|
||||
@ -405,7 +412,17 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<WasmTarget> configuration : getWasmConfigurations()) {
|
||||
CompileResult result = compileToWasm(wholeClass(children), "classTest", configuration, outputPath);
|
||||
CompileResult result = compileToWasm(WasmRuntimeType.TEAVM, wholeClass(children), "classTest",
|
||||
configuration, outputPath);
|
||||
if (!result.success) {
|
||||
hasErrors = true;
|
||||
notifier.fireTestFailure(createFailure(description, result));
|
||||
}
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<WasmTarget> configuration : getWasiConfigurations()) {
|
||||
CompileResult result = compileToWasm(WasmRuntimeType.WASI, wholeClass(children), "classTest",
|
||||
configuration, outputPath);
|
||||
if (!result.success) {
|
||||
hasErrors = true;
|
||||
notifier.fireTestFailure(createFailure(description, result));
|
||||
@ -509,6 +526,15 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
}
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<WasmTarget> configuration : getWasiConfigurations()) {
|
||||
File testPath = getOutputFile(outputPath, "classTest", configuration.getSuffix(), false, ".wasm");
|
||||
runs.add(createTestRun(configuration, testPath, child, RunKind.WASI, reference.toString(),
|
||||
notifier, onSuccess));
|
||||
File htmlPath = getOutputFile(outputPathForMethod, "test-wasm", configuration.getSuffix(), false, ".html");
|
||||
properties.put("SCRIPT", "../" + testPath.getName());
|
||||
properties.put("IDENTIFIER", reference.toString());
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<CTarget> configuration : getCConfigurations()) {
|
||||
File testPath = getOutputFile(outputPath, "classTest", configuration.getSuffix(), true, ".c");
|
||||
runs.add(createTestRun(configuration, testPath, child, RunKind.C, reference.toString(),
|
||||
@ -549,8 +575,8 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<WasmTarget> configuration : getWasmConfigurations()) {
|
||||
CompileResult compileResult = compileToWasm(singleTest(child), "test", configuration,
|
||||
outputPath);
|
||||
CompileResult compileResult = compileToWasm(WasmRuntimeType.TEAVM, singleTest(child),
|
||||
"test", configuration, outputPath);
|
||||
TestRun run = prepareRun(configuration, child, compileResult, notifier, RunKind.WASM, onSuccess);
|
||||
if (run != null) {
|
||||
runs.add(run);
|
||||
@ -567,6 +593,19 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (TeaVMTestConfiguration<WasmTarget> configuration : getWasiConfigurations()) {
|
||||
CompileResult compileResult = compileToWasm(WasmRuntimeType.WASI, singleTest(child), "test",
|
||||
configuration, outputPath);
|
||||
TestRun run = prepareRun(configuration, child, compileResult, notifier, RunKind.WASI, onSuccess);
|
||||
if (run != null) {
|
||||
runs.add(run);
|
||||
|
||||
File testPath = getOutputFile(outputPath, "test", configuration.getSuffix(), false, ".wasm");
|
||||
properties.put("SCRIPT", testPath.getName());
|
||||
properties.put("IDENTIFIER", "");
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
notifier.fireTestFailure(new Failure(describeChild(child), e));
|
||||
notifier.fireTestFinished(describeChild(child));
|
||||
@ -970,8 +1009,6 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
info.runner.init();
|
||||
}
|
||||
info.runner.run(run);
|
||||
|
||||
RunKind kind = run.getKind();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1059,9 +1096,14 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
return cTarget;
|
||||
}
|
||||
|
||||
private CompileResult compileToWasm(Consumer<TeaVM> additionalProcessing, String baseName,
|
||||
TeaVMTestConfiguration<WasmTarget> configuration, File path) {
|
||||
return compile(configuration, WasmTarget::new, TestNativeEntryPoint.class.getName(), path,
|
||||
private CompileResult compileToWasm(WasmRuntimeType runtimeType, Consumer<TeaVM> additionalProcessing,
|
||||
String baseName, TeaVMTestConfiguration<WasmTarget> configuration, File path) {
|
||||
Supplier<WasmTarget> targetSupplier = () -> {
|
||||
WasmTarget target = new WasmTarget();
|
||||
target.setRuntimeType(runtimeType);
|
||||
return target;
|
||||
};
|
||||
return compile(configuration, targetSupplier, TestNativeEntryPoint.class.getName(), path,
|
||||
".wasm", null, false, additionalProcessing, baseName);
|
||||
}
|
||||
|
||||
@ -1234,6 +1276,17 @@ public class TeaVMTestRunner extends Runner implements Filterable {
|
||||
return configurations;
|
||||
}
|
||||
|
||||
private List<TeaVMTestConfiguration<WasmTarget>> getWasiConfigurations() {
|
||||
List<TeaVMTestConfiguration<WasmTarget>> configurations = new ArrayList<>();
|
||||
if (Boolean.getBoolean(WASI_ENABLED)) {
|
||||
configurations.add(TeaVMTestConfiguration.WASM_DEFAULT);
|
||||
if (Boolean.getBoolean(OPTIMIZED)) {
|
||||
configurations.add(TeaVMTestConfiguration.WASM_OPTIMIZED);
|
||||
}
|
||||
}
|
||||
return configurations;
|
||||
}
|
||||
|
||||
private List<TeaVMTestConfiguration<CTarget>> getCConfigurations() {
|
||||
List<TeaVMTestConfiguration<CTarget>> configurations = new ArrayList<>();
|
||||
if (Boolean.getBoolean(C_ENABLED)) {
|
||||
|
131
tools/junit/src/main/java/org/teavm/junit/WasiRunStrategy.java
Normal file
131
tools/junit/src/main/java/org/teavm/junit/WasiRunStrategy.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2018 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.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
class WasiRunStrategy implements TestRunStrategy {
|
||||
private String runCommand;
|
||||
|
||||
WasiRunStrategy(String runCommand) {
|
||||
this.runCommand = runCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAll() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeThread() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterThread() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTest(TestRun run) throws IOException {
|
||||
try {
|
||||
List<String> commandLine = new ArrayList<>();
|
||||
commandLine.add(this.runCommand);
|
||||
commandLine.add(new File(run.getBaseDirectory(), run.getFileName()).getAbsolutePath());
|
||||
if (run.getArgument() != null) {
|
||||
commandLine.add(run.getArgument());
|
||||
}
|
||||
List<String> runtimeOutput = new ArrayList<>();
|
||||
List<String> stdout = new ArrayList<>();
|
||||
synchronized (this) {
|
||||
runProcess(new ProcessBuilder(commandLine.toArray(new String[0])).start(), runtimeOutput, stdout);
|
||||
}
|
||||
if (!stdout.isEmpty() && stdout.get(stdout.size() - 1).equals("SUCCESS")) {
|
||||
writeLines(runtimeOutput);
|
||||
run.getCallback().complete();
|
||||
} else {
|
||||
run.getCallback().error(new RuntimeException("Test failed:\n" + mergeLines(runtimeOutput)));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
run.getCallback().complete();
|
||||
}
|
||||
}
|
||||
|
||||
private String mergeLines(List<String> lines) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
sb.append(line).append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void writeLines(List<String> lines) {
|
||||
for (String line : lines) {
|
||||
System.out.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean runProcess(Process process, List<String> output, List<String> stdout) throws InterruptedException {
|
||||
BufferedReader stdin = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
BufferedReader stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
ConcurrentLinkedQueue<String> lines = new ConcurrentLinkedQueue<>();
|
||||
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
while (true) {
|
||||
String line = stderr.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
lines.add(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
String line = stdin.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
lines.add(line);
|
||||
stdout.add(line);
|
||||
if (lines.size() > 10000) {
|
||||
output.addAll(lines);
|
||||
process.destroy();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
boolean result = process.waitFor() == 0;
|
||||
output.addAll(lines);
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user