mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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",
|
||||
Throwable.class, String.class);
|
||||
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.exportType("TestClass", cons.getClassName());
|
||||
vm.setDebugEmitter(debugInfoBuilder);
|
||||
|
|
|
@ -264,7 +264,7 @@ public class TeaVMTool {
|
|||
if (mainClass != null) {
|
||||
MethodDescriptor mainMethodDesc = new MethodDescriptor("main", String[].class, void.class);
|
||||
vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc))
|
||||
.withValue(1, "java.lang.String");
|
||||
.withValue(1, "java.lang.String").async();
|
||||
}
|
||||
for (ClassAlias alias : classAliases) {
|
||||
vm.exportType(alias.getAlias(), alias.getClassName());
|
||||
|
@ -272,7 +272,7 @@ public class TeaVMTool {
|
|||
for (MethodAlias methodAlias : methodAliases) {
|
||||
MethodReference ref = new MethodReference(methodAlias.getClassName(), methodAlias.getMethodName(),
|
||||
MethodDescriptor.parseSignature(methodAlias.getDescriptor()));
|
||||
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref);
|
||||
TeaVMEntryPoint entryPoint = vm.entryPoint(methodAlias.getAlias(), ref).async();
|
||||
if (methodAlias.getTypes() != null) {
|
||||
for (int i = 0; i < methodAlias.getTypes().length; ++i) {
|
||||
String types = methodAlias.getTypes()[i];
|
||||
|
@ -299,6 +299,9 @@ public class TeaVMTool {
|
|||
cancelled = true;
|
||||
return;
|
||||
}
|
||||
if (mainClass != null) {
|
||||
writer.append("main = $rt_rootInvocationAdapter(main);\n");
|
||||
}
|
||||
ProblemProvider problemProvider = vm.getProblemProvider();
|
||||
if (problemProvider.getProblems().isEmpty()) {
|
||||
log.info("JavaScript file successfully built");
|
||||
|
|
|
@ -89,6 +89,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
private TeaVMProgressListener progressListener;
|
||||
private boolean cancelled;
|
||||
private ListableClassHolderSource writtenClasses;
|
||||
private Set<MethodReference> asyncMethods = new HashSet<>();
|
||||
|
||||
TeaVM(ClassReaderSource classSource, ClassLoader classLoader) {
|
||||
this.classSource = classSource;
|
||||
|
@ -435,9 +436,16 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
renderer.renderStringPool();
|
||||
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
|
||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws()
|
||||
.append("$rt_rootInvocationAdapter(")
|
||||
.appendMethodBody(entry.getValue().reference).append(");").softNewLine();
|
||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws();
|
||||
boolean wrapAsync = !asyncMethods.contains(entry.getValue().reference) && entry.getValue().isAsync();
|
||||
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()) {
|
||||
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) {
|
||||
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics);
|
||||
asyncFinder.find(classes);
|
||||
asyncMethods.addAll(asyncMethods);
|
||||
|
||||
progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size());
|
||||
Decompiler decompiler = new Decompiler(classes, classLoader, asyncFinder.getAsyncMethods());
|
||||
|
|
|
@ -72,6 +72,7 @@ public class TeaVMEntryPoint {
|
|||
private String publicName;
|
||||
MethodReference reference;
|
||||
private MethodDependency method;
|
||||
private boolean async;
|
||||
|
||||
TeaVMEntryPoint(String publicName, MethodReference reference, MethodDependency method) {
|
||||
this.publicName = publicName;
|
||||
|
@ -84,6 +85,10 @@ public class TeaVMEntryPoint {
|
|||
return publicName;
|
||||
}
|
||||
|
||||
boolean isAsync() {
|
||||
return async;
|
||||
}
|
||||
|
||||
public TeaVMEntryPoint withValue(int argument, String type) {
|
||||
if (argument > 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));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TeaVMEntryPoint async() {
|
||||
this.async = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -411,12 +411,12 @@ function $rt_asyncAdapter(f) {
|
|||
try {
|
||||
result = f.apply(this, args);
|
||||
} 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() {
|
||||
var args = Array.prototype.slice.apply(arguments);
|
||||
if (extraArgs) {
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
JUnitServer = function() {
|
||||
"use strict";
|
||||
function JUnitServer() {
|
||||
this.tree = new Tree(document.getElementById("test-tree"));
|
||||
this.totalTimeSpent = 0;
|
||||
this.expectedExceptions = [];
|
||||
|
@ -113,11 +114,10 @@ JUnitServer.prototype.runTest = function(node, callback) {
|
|||
this.currentTestNode = node;
|
||||
var self = this;
|
||||
this.loadCode(node.testCase.script, node.testCase.additionalScripts, function() {
|
||||
messageHandler = function(event) {
|
||||
function messageHandler(event) {
|
||||
window.removeEventListener("message", messageHandler);
|
||||
var timeSpent = new Date().getTime() - startTime;
|
||||
node.timeIndicator.appendChild(document.createTextNode(
|
||||
"(" + (timeSpent / 1000).toFixed(3) + ")"));
|
||||
node.timeIndicator.appendChild(document.createTextNode("(" + (timeSpent / 1000).toFixed(3) + ")"));
|
||||
self.handleEvent(JSON.parse(event.data), callback);
|
||||
};
|
||||
window.addEventListener("message", messageHandler);
|
||||
|
@ -134,8 +134,7 @@ JUnitServer.prototype.runTest = function(node, callback) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
node.indicator.className = "complete-indicator " +
|
||||
(node.success ? "successfull" : "failed");
|
||||
node.indicator.className = "complete-indicator " + (node.success ? "successfull" : "failed");
|
||||
if (!node.success) {
|
||||
node.open();
|
||||
}
|
||||
|
@ -253,7 +252,7 @@ JUnitServer.prototype.cleanupNode = function(node) {
|
|||
}
|
||||
}
|
||||
|
||||
Tree = function(container) {
|
||||
function Tree(container) {
|
||||
this.container = container;
|
||||
this.nodes = [];
|
||||
this.selectedNode = null;
|
||||
|
@ -288,7 +287,7 @@ Tree.prototype.getNodes = function() {
|
|||
Tree.prototype.addSelectionListener = function(listener) {
|
||||
this.selectionListeners.push(listener);
|
||||
}
|
||||
TreeNode = function(elem, content, button, children, tree) {
|
||||
function TreeNode(elem, content, button, children, tree) {
|
||||
this.elem = elem;
|
||||
this.content = content;
|
||||
this.button = button;
|
||||
|
@ -367,31 +366,41 @@ TreeNode.prototype.select = function() {
|
|||
}
|
||||
}
|
||||
|
||||
JUnitClient = {};
|
||||
var JUnitClient = {};
|
||||
JUnitClient.run = function() {
|
||||
var handler = window.addEventListener("message", function() {
|
||||
window.removeEventListener("message", handler);
|
||||
var message = {};
|
||||
try {
|
||||
var instance = new TestClass();
|
||||
initInstance(instance);
|
||||
runTest(instance);
|
||||
message.status = "ok";
|
||||
runTest(instance, function(restore) {
|
||||
var message = {};
|
||||
try {
|
||||
var result = restore();
|
||||
message.status = "ok";
|
||||
} catch (e) {
|
||||
JUnitClient.makeErrorMessage(message, e);
|
||||
}
|
||||
window.parent.postMessage(JSON.stringify(message), "*");
|
||||
});
|
||||
} catch (e) {
|
||||
message.status = "exception";
|
||||
if (e.$javaException && e.$javaException.constructor.$meta) {
|
||||
message.exception = e.$javaException.constructor.$meta.name;
|
||||
message.stack = e.$javaException.constructor.$meta.name + ": ";
|
||||
var exceptionMessage = extractException(e.$javaException);
|
||||
message.stack += exceptionMessage ? $rt_ustr(exceptionMessage) : "";
|
||||
message.stack += "\n" + e.stack;
|
||||
} else {
|
||||
message.stack = e.stack;
|
||||
}
|
||||
JUnitClient.makeErrorMessage(message, e);
|
||||
window.parent.postMessage(JSON.stringify(message), "*");
|
||||
}
|
||||
window.parent.postMessage(JSON.stringify(message), "*");
|
||||
});
|
||||
}
|
||||
JUnitClient.makeErrorMessage = function(message, e) {
|
||||
message.status = "exception";
|
||||
if (e.$javaException && e.$javaException.constructor.$meta) {
|
||||
message.exception = e.$javaException.constructor.$meta.name;
|
||||
message.stack = e.$javaException.constructor.$meta.name + ": ";
|
||||
var exceptionMessage = extractException(e.$javaException);
|
||||
message.stack += exceptionMessage ? $rt_ustr(exceptionMessage) : "";
|
||||
message.stack += "\n" + e.stack;
|
||||
} else {
|
||||
message.stack = e.stack;
|
||||
}
|
||||
}
|
||||
JUnitClient.reportError = function(error) {
|
||||
var handler = window.addEventListener("message", function() {
|
||||
window.removeEventListener("message", handler);
|
||||
|
|
Loading…
Reference in New Issue
Block a user