wasm gc: support running tests

This commit is contained in:
Alexey Andreev 2024-08-02 20:40:10 +02:00
parent 5eb1e7d9bc
commit 59259c314d
9 changed files with 215 additions and 4 deletions

View File

@ -59,6 +59,9 @@ tasks.test {
systemProperty("teavm.junit.wasm", providers.gradleProperty("teavm.tests.wasm").orElse("true").get()) systemProperty("teavm.junit.wasm", providers.gradleProperty("teavm.tests.wasm").orElse("true").get())
systemProperty("teavm.junit.wasm.runner", browser) systemProperty("teavm.junit.wasm.runner", browser)
systemProperty("teavm.junit.wasm-gc", providers.gradleProperty("teavm.tests.wasm-gc").orElse("false").get())
systemProperty("teavm.junit.wasm-gc.runner", browser)
systemProperty("teavm.junit.wasi", providers.gradleProperty("teavm.tests.wasi").orElse("true").get()) systemProperty("teavm.junit.wasi", providers.gradleProperty("teavm.tests.wasi").orElse("true").get())
systemProperty("teavm.junit.wasi.runner", providers.gradleProperty("teavm.tests.wasi.runner") systemProperty("teavm.junit.wasi.runner", providers.gradleProperty("teavm.tests.wasi.runner")
.orElse("./run-wasi.sh").get()) .orElse("./run-wasi.sh").get())

View File

@ -19,7 +19,7 @@
window.addEventListener("message", event => { window.addEventListener("message", event => {
let request = event.data; let request = event.data;
switch (request.type) { switch (request.type) {
case "JAVASCRIPT": case "JAVASCRIPT": {
const files = request.additionalFiles ? [...request.additionalFiles, request.file] : [request.file]; const files = request.additionalFiles ? [...request.additionalFiles, request.file] : [request.file];
appendFiles(files, 0, () => { appendFiles(files, 0, () => {
launchTest(request.argument, response => { launchTest(request.argument, response => {
@ -29,8 +29,8 @@ window.addEventListener("message", event => {
event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error }), "*"); event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error }), "*");
}); });
break; break;
}
case "WASM": case "WASM": {
const runtimeFile = request.file.path + "-runtime.js"; const runtimeFile = request.file.path + "-runtime.js";
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => { appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
launchWasmTest(request.file, request.argument, response => { launchWasmTest(request.file, request.argument, response => {
@ -41,6 +41,19 @@ window.addEventListener("message", event => {
}); });
break; break;
} }
case "WASM_GC": {
const runtimeFile = request.file.path + "-runtime.js";
appendFiles([{ path: runtimeFile, type: "regular" }], 0, () => {
launchWasmTest(request.file, request.argument, response => {
event.source.postMessage(response, "*");
});
}, error => {
event.source.postMessage(wrapResponse({ status: "failed", errorMessage: error} ), "*");
});
break;
}
}
}); });
function appendFiles(files, index, callback, errorCallback) { function appendFiles(files, index, callback, errorCallback) {

View File

@ -25,6 +25,7 @@ final class PropertyNames {
static final String WASM_ENABLED = "teavm.junit.wasm"; static final String WASM_ENABLED = "teavm.junit.wasm";
static final String WASI_ENABLED = "teavm.junit.wasi"; static final String WASI_ENABLED = "teavm.junit.wasi";
static final String WASI_RUNNER = "teavm.junit.wasi.runner"; static final String WASI_RUNNER = "teavm.junit.wasi.runner";
static final String WASM_GC_ENABLED = "teavm.junit.wasm-gc";
static final String C_COMPILER = "teavm.junit.c.compiler"; static final String C_COMPILER = "teavm.junit.c.compiler";
static final String C_LINE_NUMBERS = "teavm.junit.c.lineNumbers"; static final String C_LINE_NUMBERS = "teavm.junit.c.lineNumbers";
static final String MINIFIED = "teavm.junit.minified"; static final String MINIFIED = "teavm.junit.minified";

View File

@ -17,6 +17,7 @@ package org.teavm.junit;
import org.teavm.backend.c.CTarget; import org.teavm.backend.c.CTarget;
import org.teavm.backend.javascript.JavaScriptTarget; import org.teavm.backend.javascript.JavaScriptTarget;
import org.teavm.backend.wasm.WasmGCTarget;
import org.teavm.backend.wasm.WasmTarget; import org.teavm.backend.wasm.WasmTarget;
import org.teavm.vm.TeaVM; import org.teavm.vm.TeaVM;
import org.teavm.vm.TeaVMOptimizationLevel; import org.teavm.vm.TeaVMOptimizationLevel;
@ -115,6 +116,38 @@ interface TeaVMTestConfiguration<T extends TeaVMTarget> {
} }
}; };
TeaVMTestConfiguration<WasmGCTarget> WASM_GC_DEFAULT = new TeaVMTestConfiguration<>() {
@Override
public String getSuffix() {
return "";
}
@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
}
@Override
public void apply(WasmGCTarget target) {
}
};
TeaVMTestConfiguration<WasmGCTarget> WASM_GC_OPTIMIZED = new TeaVMTestConfiguration<>() {
@Override
public String getSuffix() {
return "optimized";
}
@Override
public void apply(TeaVM vm) {
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
}
@Override
public void apply(WasmGCTarget target) {
}
};
TeaVMTestConfiguration<CTarget> C_DEFAULT = new TeaVMTestConfiguration<>() { TeaVMTestConfiguration<CTarget> C_DEFAULT = new TeaVMTestConfiguration<>() {
@Override @Override
public String getSuffix() { public String getSuffix() {

View File

@ -106,6 +106,7 @@ public class TeaVMTestRunner extends Runner implements Filterable {
platforms.add(new JSPlatformSupport(classSource, referenceCache)); platforms.add(new JSPlatformSupport(classSource, referenceCache));
platforms.add(new WebAssemblyPlatformSupport(classSource, referenceCache)); platforms.add(new WebAssemblyPlatformSupport(classSource, referenceCache));
platforms.add(new WebAssemblyGCPlatformSupport(classSource, referenceCache));
platforms.add(new WasiPlatformSupport(classSource, referenceCache)); platforms.add(new WasiPlatformSupport(classSource, referenceCache));
platforms.add(new CPlatformSupport(classSource, referenceCache)); platforms.add(new CPlatformSupport(classSource, referenceCache));

View File

@ -19,5 +19,6 @@ public enum TestPlatform {
JAVASCRIPT, JAVASCRIPT,
WEBASSEMBLY, WEBASSEMBLY,
WASI, WASI,
WEBASSEMBLY_GC,
C C
} }

View File

@ -123,7 +123,7 @@ abstract class TestPlatformSupport<T extends TeaVMTarget> {
} }
} }
private File getOutputFile(File path, String baseName, String suffix, String extension) { protected final File getOutputFile(File path, String baseName, String suffix, String extension) {
StringBuilder simpleName = new StringBuilder(); StringBuilder simpleName = new StringBuilder();
simpleName.append(baseName); simpleName.append(baseName);
if (!suffix.isEmpty()) { if (!suffix.isEmpty()) {

View File

@ -0,0 +1,25 @@
/*
* Copyright 2021 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;
final class TestWasmGCEntryPoint {
private TestWasmGCEntryPoint() {
}
public static void main(String[] args) throws Throwable {
TestEntryPoint.run(args.length > 0 ? args[0] : null);
}
}

View File

@ -0,0 +1,134 @@
/*
* Copyright 2024 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 static org.teavm.junit.PropertyNames.OPTIMIZED;
import static org.teavm.junit.PropertyNames.SOURCE_DIRS;
import static org.teavm.junit.PropertyNames.WASM_GC_ENABLED;
import static org.teavm.junit.PropertyNames.WASM_RUNNER;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.teavm.backend.wasm.WasmGCTarget;
import org.teavm.browserrunner.BrowserRunner;
import org.teavm.model.ClassHolderSource;
import org.teavm.model.MethodReference;
import org.teavm.model.ReferenceCache;
import org.teavm.vm.TeaVM;
class WebAssemblyGCPlatformSupport extends TestPlatformSupport<WasmGCTarget> {
WebAssemblyGCPlatformSupport(ClassHolderSource classSource, ReferenceCache referenceCache) {
super(classSource, referenceCache);
}
@Override
String getExtension() {
return ".wasm";
}
@Override
TestRunStrategy createRunStrategy(File outputDir) {
var runStrategyName = System.getProperty(WASM_RUNNER);
return runStrategyName != null
? new BrowserRunStrategy(outputDir, "WASM", BrowserRunner.pickBrowser(runStrategyName))
: null;
}
@Override
CompileResult compile(Consumer<TeaVM> additionalProcessing, String baseName,
TeaVMTestConfiguration<WasmGCTarget> configuration, File path, AnnotatedElement element) {
Supplier<WasmGCTarget> targetSupplier = () -> {
var target = new WasmGCTarget();
target.setObfuscated(false);
var sourceDirs = System.getProperty(SOURCE_DIRS);
if (sourceDirs != null) {
var dirs = new ArrayList<File>();
for (var tokenizer = new StringTokenizer(sourceDirs, Character.toString(File.pathSeparatorChar));
tokenizer.hasMoreTokens();) {
var dir = new File(tokenizer.nextToken());
if (dir.isDirectory()) {
dirs.add(dir);
}
}
}
return target;
};
return compile(configuration, targetSupplier, TestWasmGCEntryPoint.class.getName(), path,
".wasm", null, additionalProcessing, baseName);
}
@Override
TestPlatform getPlatform() {
return TestPlatform.WEBASSEMBLY_GC;
}
@Override
String getPath() {
return "wasm-gc";
}
@Override
boolean isEnabled() {
return Boolean.getBoolean(WASM_GC_ENABLED);
}
@Override
List<TeaVMTestConfiguration<WasmGCTarget>> getConfigurations() {
List<TeaVMTestConfiguration<WasmGCTarget>> configurations = new ArrayList<>();
configurations.add(TeaVMTestConfiguration.WASM_GC_DEFAULT);
if (Boolean.getBoolean(OPTIMIZED)) {
configurations.add(TeaVMTestConfiguration.WASM_GC_OPTIMIZED);
}
return configurations;
}
@Override
boolean usesFileName() {
return true;
}
@Override
void additionalOutput(File outputPath, File outputPathForMethod, TeaVMTestConfiguration<?> configuration,
MethodReference reference) {
htmlOutput(outputPath, outputPathForMethod, configuration, reference, "teavm-run-test-wasm.html");
var testPath = getOutputFile(outputPath, "classTest", configuration.getSuffix(),
getExtension() + "-runtime.js");
try {
TestUtil.resourceToFile("org/teavm/backend/wasm/wasm-gc-runtime.js", testPath, Map.of());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
void additionalSingleTestOutput(File outputPathForMethod, TeaVMTestConfiguration<?> configuration,
MethodReference reference) {
htmlSingleTestOutput(outputPathForMethod, configuration, "teavm-run-test-wasm.html");
var testPath = getOutputFile(outputPathForMethod, "test", configuration.getSuffix(),
getExtension() + "-runtime.js");
try {
TestUtil.resourceToFile("org/teavm/backend/wasm/wasm-gc-runtime.js", testPath, Map.of());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}