mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Support async code in junit
This commit is contained in:
parent
484bf61a5c
commit
1f8ef1092c
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 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.classlib.java.lang;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class ThreadTest {
|
||||||
|
@Test
|
||||||
|
public void sleeps() throws InterruptedException {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
Thread.sleep(100);
|
||||||
|
long duration = System.currentTimeMillis() - start;
|
||||||
|
assertTrue("Thread.sleed did not wait enogh", duration < 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void catchesAsyncException() {
|
||||||
|
try {
|
||||||
|
throwException();
|
||||||
|
fail("Exception should have been thrown");
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// all is ok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwException() {
|
||||||
|
Thread.yield();
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -361,7 +361,7 @@ public class TeaVMTestTool {
|
||||||
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
|
MethodReference exceptionMsg = new MethodReference(ExceptionHelper.class, "showException",
|
||||||
Throwable.class, String.class);
|
Throwable.class, String.class);
|
||||||
vm.entryPoint("initInstance", cons);
|
vm.entryPoint("initInstance", cons);
|
||||||
vm.entryPoint("runTest", methodRef).withValue(0, cons.getClassName());
|
vm.entryPoint("runTest", methodRef).withValue(0, cons.getClassName()).async();
|
||||||
vm.entryPoint("extractException", exceptionMsg);
|
vm.entryPoint("extractException", exceptionMsg);
|
||||||
vm.exportType("TestClass", cons.getClassName());
|
vm.exportType("TestClass", cons.getClassName());
|
||||||
vm.setDebugEmitter(debugInfoBuilder);
|
vm.setDebugEmitter(debugInfoBuilder);
|
||||||
|
|
|
@ -264,7 +264,7 @@ public class TeaVMTool {
|
||||||
if (mainClass != null) {
|
if (mainClass != null) {
|
||||||
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", String[].class, void.class);
|
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", String[].class, void.class);
|
||||||
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
||||||
.withValue(1, "java.lang.String");
|
.withValue(1, "java.lang.String").async();
|
||||||
}
|
}
|
||||||
for (ClassAlias alias : classAliases) {
|
for (ClassAlias alias : classAliases) {
|
||||||
vm.exportType(alias.getAlias(), alias.getClassName());
|
vm.exportType(alias.getAlias(), alias.getClassName());
|
||||||
|
@ -272,7 +272,7 @@ public class TeaVMTool {
|
||||||
for (MethodAlias methodAlias : methodAliases) {
|
for (MethodAlias methodAlias : methodAliases) {
|
||||||
MethodReference ref = new MethodReference(methodAlias.getClassName(), methodAlias.getMethodName(),
|
MethodReference ref = new MethodReference(methodAlias.getClassName(), methodAlias.getMethodName(),
|
||||||
MethodDescriptor.parseSignature(methodAlias.getDescriptor()));
|
MethodDescriptor.parseSignature(methodAlias.getDescriptor()));
|
||||||
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref);
|
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref).async();
|
||||||
if (methodAlias.getTypes() != null) {
|
if (methodAlias.getTypes() != null) {
|
||||||
for (int i = 0; i < methodAlias.getTypes().length; ++i) {
|
for (int i = 0; i < methodAlias.getTypes().length; ++i) {
|
||||||
String types = methodAlias.getTypes()[i];
|
String types = methodAlias.getTypes()[i];
|
||||||
|
@ -299,6 +299,9 @@ public class TeaVMTool {
|
||||||
cancelled = true;
|
cancelled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mainClass != null) {
|
||||||
|
writer.append("main = $rt_rootInvocationAdapter(main);\n");
|
||||||
|
}
|
||||||
ProblemProvider problemProvider = vm.getProblemProvider();
|
ProblemProvider problemProvider = vm.getProblemProvider();
|
||||||
if (problemProvider.getProblems().isEmpty()) {
|
if (problemProvider.getProblems().isEmpty()) {
|
||||||
log.info("JavaScript file successfully built");
|
log.info("JavaScript file successfully built");
|
||||||
|
|
|
@ -89,6 +89,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
private TeaVMProgressListener progressListener;
|
private TeaVMProgressListener progressListener;
|
||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
private ListableClassHolderSource writtenClasses;
|
private ListableClassHolderSource writtenClasses;
|
||||||
|
private Set<MethodReference> asyncMethods = new HashSet<>();
|
||||||
|
|
||||||
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
|
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
|
@ -435,9 +436,16 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
renderer.renderStringPool();
|
renderer.renderStringPool();
|
||||||
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
|
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
|
||||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
|
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws();
|
||||||
.append("$rt_rootInvocationAdapter(")
|
boolean wrapAsync = !asyncMethods.contains(entry.getValue().reference) && entry.getValue().isAsync();
|
||||||
.appendMethodBody(entry.getValue().reference).append(");").softNewLine();
|
if (wrapAsync) {
|
||||||
|
sourceWriter.append("$rt_asyncAdapter(");
|
||||||
|
}
|
||||||
|
sourceWriter.appendMethodBody(entry.getValue().reference);
|
||||||
|
if (wrapAsync) {
|
||||||
|
sourceWriter.append(")");
|
||||||
|
}
|
||||||
|
sourceWriter.append(";").softNewLine();
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, String> entry : exportedClasses.entrySet()) {
|
for (Map.Entry<String, String> entry : exportedClasses.entrySet()) {
|
||||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
|
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
|
||||||
|
@ -529,6 +537,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
private List<ClassNode> modelToAst(ListableClassHolderSource classes) {
|
private List<ClassNode> modelToAst(ListableClassHolderSource classes) {
|
||||||
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics);
|
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics);
|
||||||
asyncFinder.find(classes);
|
asyncFinder.find(classes);
|
||||||
|
asyncMethods.addAll(asyncMethods);
|
||||||
|
|
||||||
progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size());
|
progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size());
|
||||||
Decompiler decompiler = new Decompiler(classes, classLoader, asyncFinder.getAsyncMethods());
|
Decompiler decompiler = new Decompiler(classes, classLoader, asyncFinder.getAsyncMethods());
|
||||||
|
|
|
@ -72,6 +72,7 @@ public class TeaVMEntryPoint {
|
||||||
private String publicName;
|
private String publicName;
|
||||||
MethodReference reference;
|
MethodReference reference;
|
||||||
private MethodDependency method;
|
private MethodDependency method;
|
||||||
|
private boolean async;
|
||||||
|
|
||||||
TeaVMEntryPoint(String publicName, MethodReference reference, MethodDependency method) {
|
TeaVMEntryPoint(String publicName, MethodReference reference, MethodDependency method) {
|
||||||
this.publicName = publicName;
|
this.publicName = publicName;
|
||||||
|
@ -84,6 +85,10 @@ public class TeaVMEntryPoint {
|
||||||
return publicName;
|
return publicName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isAsync() {
|
||||||
|
return async;
|
||||||
|
}
|
||||||
|
|
||||||
public TeaVMEntryPoint withValue(int argument, String type) {
|
public TeaVMEntryPoint withValue(int argument, String type) {
|
||||||
if (argument > reference.parameterCount()) {
|
if (argument > reference.parameterCount()) {
|
||||||
throw new IllegalArgumentException("Illegal argument #" + argument + " of " + reference.parameterCount());
|
throw new IllegalArgumentException("Illegal argument #" + argument + " of " + reference.parameterCount());
|
||||||
|
@ -91,4 +96,9 @@ public class TeaVMEntryPoint {
|
||||||
method.getVariable(argument).propagate(method.getDependencyAgent().getType(type));
|
method.getVariable(argument).propagate(method.getDependencyAgent().getType(type));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TeaVMEntryPoint async() {
|
||||||
|
this.async = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -411,12 +411,12 @@ function $rt_asyncAdapter(f) {
|
||||||
try {
|
try {
|
||||||
result = f.apply(this, args);
|
result = f.apply(this, args);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return $rt_asyncError(e);
|
return $return($rt_asyncError(e));
|
||||||
}
|
}
|
||||||
return $rt_asyncResult(result);
|
return $return($rt_asyncResult(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function $rt_rootInvocationAdapter(f, extraArgs) {
|
function $rt_rootInvocationAdapter(f) {
|
||||||
return function() {
|
return function() {
|
||||||
var args = Array.prototype.slice.apply(arguments);
|
var args = Array.prototype.slice.apply(arguments);
|
||||||
if (extraArgs) {
|
if (extraArgs) {
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
JUnitServer = function() {
|
"use strict";
|
||||||
|
function JUnitServer() {
|
||||||
this.tree = new Tree(document.getElementById("test-tree"));
|
this.tree = new Tree(document.getElementById("test-tree"));
|
||||||
this.totalTimeSpent = 0;
|
this.totalTimeSpent = 0;
|
||||||
this.expectedExceptions = [];
|
this.expectedExceptions = [];
|
||||||
|
@ -113,11 +114,10 @@ JUnitServer.prototype.runTest = function(node, callback) {
|
||||||
this.currentTestNode = node;
|
this.currentTestNode = node;
|
||||||
var self = this;
|
var self = this;
|
||||||
this.loadCode(node.testCase.script, node.testCase.additionalScripts, function() {
|
this.loadCode(node.testCase.script, node.testCase.additionalScripts, function() {
|
||||||
messageHandler = function(event) {
|
function messageHandler(event) {
|
||||||
window.removeEventListener("message", messageHandler);
|
window.removeEventListener("message", messageHandler);
|
||||||
var timeSpent = new Date().getTime() - startTime;
|
var timeSpent = new Date().getTime() - startTime;
|
||||||
node.timeIndicator.appendChild(document.createTextNode(
|
node.timeIndicator.appendChild(document.createTextNode("(" + (timeSpent / 1000).toFixed(3) + ")"));
|
||||||
"(" + (timeSpent / 1000).toFixed(3) + ")"));
|
|
||||||
self.handleEvent(JSON.parse(event.data), callback);
|
self.handleEvent(JSON.parse(event.data), callback);
|
||||||
};
|
};
|
||||||
window.addEventListener("message", messageHandler);
|
window.addEventListener("message", messageHandler);
|
||||||
|
@ -134,8 +134,7 @@ JUnitServer.prototype.runTest = function(node, callback) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.indicator.className = "complete-indicator " +
|
node.indicator.className = "complete-indicator " + (node.success ? "successfull" : "failed");
|
||||||
(node.success ? "successfull" : "failed");
|
|
||||||
if (!node.success) {
|
if (!node.success) {
|
||||||
node.open();
|
node.open();
|
||||||
}
|
}
|
||||||
|
@ -253,7 +252,7 @@ JUnitServer.prototype.cleanupNode = function(node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree = function(container) {
|
function Tree(container) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
this.selectedNode = null;
|
this.selectedNode = null;
|
||||||
|
@ -288,7 +287,7 @@ Tree.prototype.getNodes = function() {
|
||||||
Tree.prototype.addSelectionListener = function(listener) {
|
Tree.prototype.addSelectionListener = function(listener) {
|
||||||
this.selectionListeners.push(listener);
|
this.selectionListeners.push(listener);
|
||||||
}
|
}
|
||||||
TreeNode = function(elem, content, button, children, tree) {
|
function TreeNode(elem, content, button, children, tree) {
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.button = button;
|
this.button = button;
|
||||||
|
@ -367,17 +366,30 @@ TreeNode.prototype.select = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JUnitClient = {};
|
var JUnitClient = {};
|
||||||
JUnitClient.run = function() {
|
JUnitClient.run = function() {
|
||||||
var handler = window.addEventListener("message", function() {
|
var handler = window.addEventListener("message", function() {
|
||||||
window.removeEventListener("message", handler);
|
window.removeEventListener("message", handler);
|
||||||
var message = {};
|
|
||||||
try {
|
try {
|
||||||
var instance = new TestClass();
|
var instance = new TestClass();
|
||||||
initInstance(instance);
|
initInstance(instance);
|
||||||
runTest(instance);
|
runTest(instance, function(restore) {
|
||||||
|
var message = {};
|
||||||
|
try {
|
||||||
|
var result = restore();
|
||||||
message.status = "ok";
|
message.status = "ok";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
JUnitClient.makeErrorMessage(message, e);
|
||||||
|
}
|
||||||
|
window.parent.postMessage(JSON.stringify(message), "*");
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
JUnitClient.makeErrorMessage(message, e);
|
||||||
|
window.parent.postMessage(JSON.stringify(message), "*");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
JUnitClient.makeErrorMessage = function(message, e) {
|
||||||
message.status = "exception";
|
message.status = "exception";
|
||||||
if (e.$javaException && e.$javaException.constructor.$meta) {
|
if (e.$javaException && e.$javaException.constructor.$meta) {
|
||||||
message.exception = e.$javaException.constructor.$meta.name;
|
message.exception = e.$javaException.constructor.$meta.name;
|
||||||
|
@ -389,9 +401,6 @@ JUnitClient.run = function() {
|
||||||
message.stack = e.stack;
|
message.stack = e.stack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.parent.postMessage(JSON.stringify(message), "*");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
JUnitClient.reportError = function(error) {
|
JUnitClient.reportError = function(error) {
|
||||||
var handler = window.addEventListener("message", function() {
|
var handler = window.addEventListener("message", function() {
|
||||||
window.removeEventListener("message", handler);
|
window.removeEventListener("message", handler);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user