Adds more fancy look for test runner

This commit is contained in:
Alexey Andreev 2014-03-14 19:15:04 +04:00
parent ba2a3e12e9
commit b144d474f2
15 changed files with 1355 additions and 285 deletions

View File

@ -153,9 +153,18 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
final Log log = getLog();
new File(outputDir, "tests").mkdirs();
resourceToFile("org/teavm/javascript/runtime.js", "runtime.js");
resourceToFile("org/teavm/maven/junit-support.js", "junit-support.js");
resourceToFile("org/teavm/maven/junit.css", "junit.css");
new File(outputDir, "res").mkdirs();
resourceToFile("org/teavm/javascript/runtime.js", "res/runtime.js");
resourceToFile("org/teavm/maven/res/junit-support.js", "res/junit-support.js");
resourceToFile("org/teavm/maven/res/junit.css", "res/junit.css");
resourceToFile("org/teavm/maven/res/class_obj.png", "res/class_obj.png");
resourceToFile("org/teavm/maven/res/control-000-small.png", "res/control-000-small.png");
resourceToFile("org/teavm/maven/res/methpub_obj.png", "res/methpub_obj.png");
resourceToFile("org/teavm/maven/res/package_obj.png", "res/package_obj.png");
resourceToFile("org/teavm/maven/res/tick-small-red.png", "res/tick-small-red.png");
resourceToFile("org/teavm/maven/res/tick-small.png", "res/tick-small.png");
resourceToFile("org/teavm/maven/res/toggle-small-expand.png", "res/toggle-small-expand.png");
resourceToFile("org/teavm/maven/res/toggle-small.png", "res/toggle-small.png");
resourceToFile("org/teavm/maven/junit.html", "junit.html");
final ClassHolderSource classSource = new ClasspathClassHolderSource(classLoader);
for (String testClass : testClasses) {
@ -170,8 +179,8 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
includeAdditionalScripts(classLoader);
File allTestsFile = new File(outputDir, "tests/all.js");
try (Writer allTestsWriter = new OutputStreamWriter(new FileOutputStream(allTestsFile), "UTF-8")) {
allTestsWriter.write("doRunTests = function() {\n");
allTestsWriter.write(" new JUnitServer(document.body).runAllTests([");
allTestsWriter.write("prepare = function() {\n");
allTestsWriter.write(" return new JUnitServer(document.body).readTests([");
boolean first = true;
for (String testClass : testClasses) {
if (!first) {
@ -547,3 +556,4 @@ public class BuildJavascriptTestMojo extends AbstractMojo {
}
}
}

View File

@ -1,241 +0,0 @@
/*
* Copyright 2013 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.
*/
JUnitServer = function(container) {
this.container = container;
this.timeSpent = 0;
this.totalTimeSpent = 0;
this.methodCount = 0;
this.statusCell = null;
this.exceptionCell = null;
this.timeCell = null;
this.startTime = 0;
this.expectedExceptions = [];
this.table = null;
this.tableBody = null;
this.frame = null;
}
JUnitServer.prototype = new Object();
JUnitServer.prototype.handleEvent = function(message, callback) {
endTime = new Date().getTime();
if (message.status === "ok") {
if (this.expectedExceptions.length > 0) {
this.statusCell.appendChild(document.createTextNode("expected exception not thrown"));
this.statusCell.style.color = 'yellow';
} else {
this.statusCell.appendChild(document.createTextNode("ok"));
this.statusCell.style.color = 'green';
}
} else if (message.status === "exception") {
if (message.exception && this.isExpectedException(message.exception)) {
this.statusCell.appendChild(document.createTextNode("ok"));
this.statusCell.style.color = 'green';
} else {
this.statusCell.appendChild(document.createTextNode("unexpected exception"));
var exceptionText = document.createElement("pre");
exceptionText.appendChild(document.createTextNode(message.stack));
this.exceptionCell.appendChild(exceptionText);
this.statusCell.style.color = 'red';
}
}
++this.methodCount;
var timeSpent = (endTime - this.startTime) / 1000;
this.timeSpent += timeSpent;
this.timeCell.appendChild(document.createTextNode(timeSpent.toFixed(3)));
document.body.removeChild(this.frame);
self.frame = null;
callback();
}
JUnitServer.prototype.isExpectedException = function(ex) {
for (var i = 0; i < this.expectedExceptions.length; ++i) {
if (this.expectedExceptions[i] === ex) {
return true;
}
}
return false;
}
JUnitServer.prototype.runTestCase = function(methodName, path, expectedExceptions, additionalScripts, callback) {
this.createRow(methodName);
this.startTime = new Date().getTime();
this.expectedExceptions = expectedExceptions;
var self = this;
this.loadCode(path, additionalScripts, function() {
messageHandler = function(event) {
window.removeEventListener("message", messageHandler);
self.handleEvent(JSON.parse(event.data), callback);
};
window.addEventListener("message", messageHandler);
self.frame.contentWindow.postMessage("runTest", "*");
});
}
JUnitServer.prototype.createRow = function(methodName) {
var row = document.createElement("tr");
this.tableBody.appendChild(row);
var nameCell = document.createElement("td");
row.appendChild(nameCell);
nameCell.appendChild(document.createTextNode(methodName));
this.statusCell = document.createElement("td");
row.appendChild(this.statusCell);
this.exceptionCell = document.createElement("td");
row.appendChild(this.exceptionCell);
this.timeCell = document.createElement("td");
row.appendChild(this.timeCell);
}
JUnitServer.prototype.loadCode = function(path, additionalScripts, callback) {
this.frame = document.createElement("iframe");
document.body.appendChild(this.frame);
var frameDoc = this.frame.contentWindow.document;
var self = this;
var sequence = ["junit-support.js", "runtime.js"];
if (additionalScripts) {
for (var i = 0; i < additionalScripts.length; ++i) {
sequence.push(additionalScripts[i]);
}
}
sequence.push(path);
self.loadScripts(sequence, 0, callback);
}
JUnitServer.prototype.loadScripts = function(scripts, index, callback) {
var self = this;
if (index == scripts.length) {
callback();
} else {
this.loadScript(scripts[index], function() { self.loadScripts(scripts, index + 1, callback) });
}
}
JUnitServer.prototype.loadScript = function(name, callback) {
var doc = this.frame.contentWindow.document;
var script = doc.createElement("script");
script.src = name;
doc.body.appendChild(script);
script.onload = function() {
callback();
}
}
JUnitServer.prototype.runTest = function(test, callback) {
this.timeSpent = 0;
this.methodCount = 0;
this.createTable(test.name);
var self = this;
this.runMethodFromList(test.methods, 0, function() {
self.createFooter();
callback();
});
}
JUnitServer.prototype.runAllTests = function(tests, callback) {
this.runTestFromList(tests, 0, callback);
}
JUnitServer.prototype.runTestFromList = function(tests, index, callback) {
if (index < tests.length) {
var test = tests[index];
var self = this;
this.runTest(test, function() {
self.runTestFromList(tests, index + 1, callback);
});
} else {
callback();
}
}
JUnitServer.prototype.runMethodFromList = function(methods, index, callback) {
if (index < methods.length) {
var method = methods[index];
var self = this;
this.runTestCase(method.name, method.script, method.expected, method.additionalScripts, function() {
self.runMethodFromList(methods, index + 1, callback);
});
} else {
callback();
}
}
JUnitServer.prototype.createTable = function(name) {
this.table = document.createElement("table");
this.container.appendChild(this.table);
var caption = document.createElement("caption");
this.table.appendChild(caption);
this.createHeader();
caption.appendChild(document.createTextNode(name));
this.tableBody = document.createElement("tbody");
this.table.appendChild(this.tableBody);
}
JUnitServer.prototype.createHeader = function() {
var head = document.createElement("thead");
this.table.appendChild(head);
var headRow = document.createElement("tr");
head.appendChild(headRow);
var headCell = document.createElement("th");
headRow.appendChild(headCell);
headCell.appendChild(document.createTextNode("Method"));
headCell = document.createElement("th");
headRow.appendChild(headCell);
headCell.appendChild(document.createTextNode("Result"));
headCell = document.createElement("th");
headRow.appendChild(headCell);
headCell.appendChild(document.createTextNode("Exception"));
headCell = document.createElement("th");
headRow.appendChild(headCell);
headCell.appendChild(document.createTextNode("Time spent, s"));
this.table.appendChild(head);
}
JUnitServer.prototype.createFooter = function() {
var foot = document.createElement("tfoot");
this.table.appendChild(foot);
var footRow = document.createElement("tr");
foot.appendChild(footRow);
var footName = document.createElement("td");
footRow.appendChild(footName);
footName.appendChild(document.createTextNode("---"));
var footMethods = document.createElement("td");
footRow.appendChild(footMethods);
footMethods.appendChild(document.createTextNode(this.methodCount));
var footSpace = document.createElement("td");
footRow.appendChild(footSpace);
footSpace.appendChild(document.createTextNode("---"));
var footTime = document.createElement("td");
footRow.appendChild(footTime);
footTime.appendChild(document.createTextNode(this.timeSpent.toFixed(3)));
}
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";
} 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;
}
}
window.parent.postMessage(JSON.stringify(message), "*");
});
}
JUnitClient.reportError = function(error) {
var handler = window.addEventListener("message", function() {
window.removeEventListener("message", handler);
var message = { status : "exception", stack : error };
window.parent.postMessage(JSON.stringify(message), "*");
});
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2013 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.
*/
table {
border-collapse: collapse;
border: 2px solid black;
margin: 2em 1em 2em 1em;
}
table td, table th {
border: 1px solid gray;
padding: 0.1em 0.5em 0.2em 0.5em;
}
table thead, table tfoot {
border: 2px solid black;
}
iframe {
with: 1px;
height: 1px;
padding: 0px;
margin: 0px;
border-style: none;
}

View File

@ -19,17 +19,35 @@
<title>TeaVM JUnit tests</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>TeaVM JUnit tests</title>
<link rel="stylesheet" href="junit.css" type="text/css"/>
<script type="text/javascript" src="junit-support.js"></script>
<link rel="stylesheet" href="res/junit.css" type="text/css"/>
<script type="text/javascript" src="res/junit-support.js"></script>
<script type="text/javascript" src="tests/all.js"></script>
</head>
<body>
<script type="text/javascript">
function runTests() {
document.getElementById("start-button").style.display = "none";
doRunTests();
document.getElementById("start-button").disabled = true;
server.runAllTests(function() {
document.getElementById("start-button").disabled = false;
});
}
</script>
<button id="start-button" onclick="runTests()">Run tests</button>
<div class="test-header">
<div class="test-count">Total tests:
<span id="test-count"></span><span id="total-time" class="time-indicator"></span>
</div>
<div class="failed-test-count">Failed: <span id="failed-test-count"></span></div>
<div class="progress-bar">
<div id="progress-bar-content"></div>
</div>
<button id="start-button" onclick="runTests()">Run</button>
</div>
<div id="test-tree">
</div>
<div id="test-trace">
</div>
<script>
server = prepare();
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

View File

@ -0,0 +1,400 @@
/*
* Copyright 2013 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.
*/
JUnitServer = function() {
this.tree = new Tree(document.getElementById("test-tree"));
this.totalTimeSpent = 0;
this.expectedExceptions = [];
this.frame = null;
this.tests = [];
this.currentTestNode = null;
this.testCaseCount = 0;
this.progressElem = document.getElementById("progress-bar-content");
this.runCount = 0;
this.failCount = 0;
this.traceElem = document.getElementById("test-trace");
this.failedElem = document.getElementById("failed-test-count");
this.totalTimeElem = document.getElementById("total-time");
var self = this;
this.tree.addSelectionListener(function(node) {
while (self.traceElem.firstChild) {
self.traceElem.removeChild(self.traceElem.firstChild);
}
if (node.error) {
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(node.error));
self.traceElem.appendChild(pre);
}
});
}
JUnitServer.prototype = new Object();
JUnitServer.prototype.handleEvent = function(message, callback) {
if (message.status === "ok") {
if (this.expectedExceptions.length > 0) {
this.currentTestNode.success = false;
this.currentTestNode.error = "Expected exception not thrown";
this.failCount++;
} else {
this.currentTestNode.success = true;
}
} else if (message.status === "exception") {
if (message.exception && this.isExpectedException(message.exception)) {
this.currentTestNode.success = true;
} else {
this.currentTestNode.success = false;
this.currentTestNode.error = message.stack;
this.failCount++;
}
}
this.currentTestNode.indicator.className = "complete-indicator " +
(this.currentTestNode.success ? "successfull" : "failed");
this.runCount++;
this.progressElem.style.width = (100 * this.runCount / this.testCaseCount).toFixed(2) + "%";
document.body.removeChild(this.frame);
self.frame = null;
callback();
}
JUnitServer.prototype.isExpectedException = function(ex) {
for (var i = 0; i < this.expectedExceptions.length; ++i) {
if (this.expectedExceptions[i] === ex) {
return true;
}
}
return false;
}
JUnitServer.prototype.loadCode = function(path, additionalScripts, callback) {
this.frame = document.createElement("iframe");
document.body.appendChild(this.frame);
var frameDoc = this.frame.contentWindow.document;
var self = this;
var sequence = ["res/junit-support.js", "res/runtime.js"];
if (additionalScripts) {
for (var i = 0; i < additionalScripts.length; ++i) {
sequence.push(additionalScripts[i]);
}
}
sequence.push(path);
self.loadScripts(sequence, 0, callback);
}
JUnitServer.prototype.loadScripts = function(scripts, index, callback) {
var self = this;
if (index == scripts.length) {
callback();
} else {
this.loadScript(scripts[index], function() { self.loadScripts(scripts, index + 1, callback) });
}
}
JUnitServer.prototype.loadScript = function(name, callback) {
var doc = this.frame.contentWindow.document;
var script = doc.createElement("script");
script.src = name;
doc.body.appendChild(script);
script.onload = function() {
callback();
}
}
JUnitServer.prototype.runTest = function(node, callback) {
node.indicator.className = "complete-indicator in-progress";
var startTime = new Date().getTime();
if (node.testCase) {
this.expectedExceptions = node.testCase.expected;
this.currentTestNode = node;
var self = this;
this.loadCode(node.testCase.script, node.testCase.additionalScripts, function() {
messageHandler = function(event) {
window.removeEventListener("message", messageHandler);
var timeSpent = new Date().getTime() - startTime;
node.timeIndicator.appendChild(document.createTextNode(
"(" + (timeSpent / 1000).toFixed(3) + ")"));
self.handleEvent(JSON.parse(event.data), callback);
};
window.addEventListener("message", messageHandler);
self.frame.contentWindow.postMessage("runTest", "*");
});
} else {
var self = this;
var nodes = node.getNodes();
this.runTestFromList(nodes, 0, function() {
node.success = true;
for (var i = 0; i < nodes.length; ++i) {
if (!nodes[i].success) {
node.success = false;
break;
}
}
node.indicator.className = "complete-indicator " +
(node.success ? "successfull" : "failed");
if (!node.success) {
node.open();
}
var timeSpent = new Date().getTime() - startTime;
node.timeIndicator.appendChild(document.createTextNode(
"(" + (timeSpent / 1000).toFixed(3) + ")"));
callback();
});
}
}
JUnitServer.prototype.readTests = function(tests) {
var groups = this.groupTests(tests);
var groupNames = [];
for (var groupName in groups) {
groupNames.push(groupName);
}
groupNames.sort();
this.tests = [];
for (var i = 0; i < groupNames.length; ++i) {
var groupName = groupNames[i];
var group = groups[groupName];
var pkgNode = this.createNode(this.tree, "package", groupName);
group.sort();
for (var j = 0; j < group.length; ++j) {
var test = group[j];
var simpleName = test.name.substring(groupName.length + 1);
var testNode = this.createNode(pkgNode, "test", simpleName);
var methods = test.methods.slice();
methods.sort();
for (var k = 0; k < methods.length; ++k) {
var method = methods[k];
var caseNode = this.createNode(testNode, "case", method.name);
caseNode.testCase = method;
++this.testCaseCount;
}
}
}
document.getElementById("test-count").appendChild(document.createTextNode(this.testCaseCount));
return this;
}
JUnitServer.prototype.createNode = function(parent, className, name) {
var elem = document.createElement("div");
elem.className = className;
elem.appendChild(document.createTextNode(name));
var node = parent.add(elem);
node.indicator = document.createElement("div");
node.indicator.className = "complete-indicator";
elem.appendChild(node.indicator);
node.timeIndicator = document.createElement("span");
node.timeIndicator.className = "time-indicator";
elem.appendChild(node.timeIndicator);
return node;
}
JUnitServer.prototype.groupTests = function(tests) {
var groups = {};
for (var i = 0; i < tests.length; ++i) {
var test = tests[i];
var pkg = test.name.substring(0, test.name.lastIndexOf('.'));
var group = groups[pkg];
if (!group) {
group = [];
groups[pkg] = group;
}
group.push(test);
}
return groups;
}
JUnitServer.prototype.runAllTests = function(callback) {
this.cleanupTests();
var self = this;
var startTime = new Date().getTime();
this.runTestFromList(this.tree.getNodes(), 0, function() {
self.failedElem.appendChild(document.createTextNode(self.failCount));
var totalTime = new Date().getTime() - startTime;
self.totalTimeElem.appendChild(document.createTextNode("(" +
(totalTime / 1000).toFixed(3) + ")"));
callback();
});
}
JUnitServer.prototype.runTestFromList = function(nodes, index, callback) {
if (index < nodes.length) {
var node = nodes[index];
var self = this;
this.runTest(node, function() {
self.runTestFromList(nodes, index + 1, callback);
});
} else {
callback();
}
}
JUnitServer.prototype.cleanupTests = function() {
if (this.failedElem.firstChild) {
this.failedElem.removeChild(this.failedElem.firstChild);
}
if (this.totalTimeElem.firstChild) {
this.totalTimeElem.removeChild(this.totalTimeElem.firstChild);
}
this.runCount = 0;
this.progressElem.style.width = "0%";
var nodes = this.tree.getNodes();
for (var i = 0; i < nodes.length; ++i) {
this.cleanupNode(nodes[i]);
}
}
JUnitServer.prototype.cleanupNode = function(node) {
delete node.error;
node.indicator.className = "complete-indicator";
if (node.timeIndicator.firstChild) {
node.timeIndicator.removeChild(node.timeIndicator.firstChild);
}
var nodes = node.getNodes();
for (var i = 0; i < nodes.length; ++i) {
this.cleanupNode(nodes[i]);
}
}
Tree = function(container) {
this.container = container;
this.nodes = [];
this.selectedNode = null;
this.selectionListeners = [];
}
Tree.prototype.createNode = function(content) {
var elem = document.createElement("div");
elem.className = "tree-node";
var contentElem = document.createElement("div");
contentElem.className = "tree-node-content";
elem.appendChild(contentElem);
contentElem.appendChild(content);
var buttonElem = document.createElement("div");
buttonElem.className = "tree-node-button closed";
buttonElem.style.display = "none";
elem.appendChild(buttonElem);
var childrenElem = document.createElement("div");
childrenElem.className = "tree-node-children closed";
childrenElem.style.display = "none";
elem.appendChild(childrenElem);
return new TreeNode(elem, contentElem, buttonElem, childrenElem, this);
}
Tree.prototype.add = function(content) {
var node = this.createNode(content);
this.container.appendChild(node.elem);
this.nodes.push(node);
return node;
}
Tree.prototype.getNodes = function() {
return this.nodes;
}
Tree.prototype.addSelectionListener = function(listener) {
this.selectionListeners.push(listener);
}
TreeNode = function(elem, content, button, children, tree) {
this.elem = elem;
this.content = content;
this.button = button;
this.children = children;
this.opened = false;
this.parent = null;
this.nodes = [];
this.tree = tree;
var self = this;
this.button.onclick = function() {
self.toggle();
}
this.content.onclick = function() {
self.select();
}
}
TreeNode.prototype.add = function(content) {
var node = this.tree.createNode(content);
this.children.appendChild(node.elem);
this.button.style.display = "";
this.children.style.display = "";
this.content.className = "tree-node-content";
node.parent = this;
this.nodes.push(node);
return node;
}
TreeNode.prototype.isOpened = function() {
return this.opened;
}
TreeNode.prototype.open = function() {
if (this.isOpened()) {
return;
}
this.opened = true;
this.children.className = "tree-node-children opened";
this.button.className = "tree-node-button opened";
}
TreeNode.prototype.close = function() {
if (!this.isOpened()) {
return;
}
this.opened = false;
this.children.className = "tree-node-children closed";
this.button.className = "tree-node-button closed";
}
TreeNode.prototype.toggle = function() {
if (this.isOpened()) {
this.close();
} else {
this.open();
}
}
TreeNode.prototype.getNodes = function() {
return this.nodes;
}
TreeNode.prototype.getParent = function() {
return this.parent;
}
TreeNode.prototype.getTree = function() {
return this.tree;
}
TreeNode.prototype.isSelected = function() {
return this.tree.selectedNode === this;
}
TreeNode.prototype.select = function() {
if (this.isSelected()) {
return;
}
if (this.tree.selectedNode != null) {
this.tree.selectedNode.content.className = "tree-node-content";
}
this.content.className = "tree-node-content selected";
this.tree.selectedNode = this;
for (var i = 0; i < this.tree.selectionListeners.length; ++i) {
this.tree.selectionListeners[i](this);
}
}
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";
} 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;
}
}
window.parent.postMessage(JSON.stringify(message), "*");
});
}
JUnitClient.reportError = function(error) {
var handler = window.addEventListener("message", function() {
window.removeEventListener("message", handler);
var message = { status : "exception", stack : error };
window.parent.postMessage(JSON.stringify(message), "*");
});
}

View File

@ -0,0 +1,185 @@
/*
* Copyright 2013 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.
*/
iframe {
with: 1px;
height: 1px;
padding: 0px;
margin: 0px;
border-style: none;
}
* {
font-family: sans;
font-size: 10pt;
}
html, body {
position: absolute;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
padding: 0px;
margin: 0px;
}
.test-header {
position: absolute;
top: 0px;
right: 0px;
left: 0px;
height: 40px;
border-bottom-color: gray;
border-bottom-width: 1px;
border-bottom-style: solid;
}
.test-count, .failed-test-count {
position: absolute;
top: 0px;
bottom: 0px;
line-height: 40px;
padding: 0px;
margin: 0px;
vertical-align: middle;
}
.test-count {
left: 5px;
width: 200px;
}
.failed-test-count {
left: 205px;
width: 130px;
}
#start-button {
display: block;
position: absolute;
left: 340px;
top: 6px;
bottom: 6px;
width: 70px;
}
.progress-bar {
position: absolute;
left: 420px;
right: 20px;
top: 5px;
height: 30px;
border-color: grey;
border-radius: 2px;
border-width: 1px;
border-style: solid;
}
#progress-bar-content {
position: absolute;
background-color: green;
left: 0px;
top: 0px;
bottom: 0px;
width: 0%;
}
#test-tree {
position: absolute;
top: 41px;
bottom: 0px;
left: 0px;
width: 50%;
border-right-color: grey;
border-right-width: 1px;
border-right-style: solid;
overflow: auto;
}
#test-trace {
position: absolute;
top: 41px;
bottom: 0px;
left: 50%;
right: 0px;
overflow: auto;
}
.tree-node {
position: relative;
}
.tree-node-content {
margin-left: 18px;
cursor: default;
white-space: nowrap;
}
.tree-node-content.selected {
background-color: rgb(160,160,255);
}
.tree-node-children {
padding-left: 18px;
}
.tree-node-children.closed {
display: none;
}
.tree-node-button {
position: absolute;
cursor: pointer;
left: 0px;
top: 0px;
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-position: 0px 0px;
}
.tree-node-button.opened {
background-image: url(toggle-small.png);
}
.tree-node-button.closed {
background-image: url(toggle-small-expand.png);
}
.package, .test, .case {
min-height: 18px;
padding-left: 20px;
background-position: 2px 1px;
background-repeat: no-repeat;
position: relative;
}
.package {
background-image: url(package_obj.png);
}
.test {
background-image: url(class_obj.png);
}
.case {
background-image: url(methpub_obj.png);
}
.complete-indicator {
position: absolute;
left: -4px;
top: 5px;
width: 16px;
height: 16px;
background-position: 0px 0px;
background-repeat: no-repeat;
display: none;
}
.complete-indicator.successfull {
display: block;
background-image: url(tick-small.png);
}
.complete-indicator.failed {
display: block;
background-image: url(tick-small-red.png);
}
.complete-indicator.in-progress {
display: block;
background-image: url(control-000-small.png);
}
.time-indicator {
font-size: 9pt;
font-style: italic;
color: rgb(0,80,160);
padding-left: 0.5em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

View File

@ -0,0 +1,732 @@
/*
* Copyright 2013 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.
*/
$rt_lastObjectId = 0;
$rt_nextId = function() {
return $rt_lastObjectId++;
}
$rt_compare = function(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
}
$rt_isInstance = function(obj, cls) {
return obj != null && obj.constructor.$meta && $rt_isAssignable(obj.constructor, cls);
}
$rt_isAssignable = function(from, to) {
if (from === to) {
return true;
}
var supertypes = from.$meta.supertypes;
for (var i = 0; i < supertypes.length; i = (i + 1) | 0) {
if ($rt_isAssignable(supertypes[i], to)) {
return true;
}
}
return false;
}
$rt_createArray = function(cls, sz) {
var data = new Array(sz);
var arr = new ($rt_arraycls(cls))(data);
for (var i = 0; i < sz; i = (i + 1) | 0) {
data[i] = null;
}
return arr;
}
$rt_wrapArray = function(cls, data) {
var arr = new ($rt_arraycls(cls))(data);
return arr;
}
$rt_createUnfilledArray = function(cls, sz) {
return new ($rt_arraycls(cls))(new Array(sz));
}
$rt_createLongArray = function(sz) {
var data = new Array(sz);
var arr = new ($rt_arraycls($rt_longcls()))(data);
for (var i = 0; i < sz; i = (i + 1) | 0) {
data[i] = Long.ZERO;
}
return arr;
}
if (ArrayBuffer) {
$rt_createNumericArray = function(cls, nativeArray) {
return new ($rt_arraycls(cls))(nativeArray);
}
$rt_createByteArray = function(sz) {
return $rt_createNumericArray($rt_bytecls(), new Int8Array(new ArrayBuffer(sz)), 0);
};
$rt_createShortArray = function(sz) {
return $rt_createNumericArray($rt_shortcls(), new Int16Array(new ArrayBuffer(sz << 1)), 0);
};
$rt_createIntArray = function(sz) {
return $rt_createNumericArray($rt_intcls(), new Int32Array(new ArrayBuffer(sz << 2)), 0);
};
$rt_createBooleanArray = function(sz) {
return $rt_createNumericArray($rt_booleancls(), new Int8Array(new ArrayBuffer(sz)), 0);
};
$rt_createFloatArray = function(sz) {
return $rt_createNumericArray($rt_floatcls(), new Float32Array(new ArrayBuffer(sz << 2)), 0);
};
$rt_createDoubleArray = function(sz) {
return $rt_createNumericArray($rt_doublecls(), new Float64Array(new ArrayBuffer(sz << 3)), 0);
};
$rt_createCharArray = function(sz) {
return $rt_createNumericArray($rt_charcls(), new Uint16Array(new ArrayBuffer(sz << 1)), 0);
};
} else {
$rt_createNumericArray = function(cls, sz) {
var data = new Array(sz);
var arr = new ($rt_arraycls(cls))(data);
for (var i = 0; i < sz; i = (i + 1) | 0) {
data[i] = 0;
}
return arr;
}
$rt_createByteArray = function(sz) { return $rt_createNumericArray($rt_bytecls(), sz); }
$rt_createShortArray = function(sz) { return $rt_createNumericArray($rt_shortcls(), sz); }
$rt_createIntArray = function(sz) { return $rt_createNumericArray($rt_intcls(), sz); }
$rt_createBooleanArray = function(sz) { return $rt_createNumericArray($rt_booleancls(), sz); }
$rt_createFloatArray = function(sz) { return $rt_createNumericArray($rt_floatcls(), sz); }
$rt_createDoubleArray = function(sz) { return $rt_createNumericArray($rt_doublecls(), sz); }
$rt_createCharArray = function(sz) { return $rt_createNumericArray($rt_charcls(), sz); }
}
$rt_arraycls = function(cls) {
if (cls.$array == undefined) {
var arraycls = function(data) {
this.data = data;
this.$id = $rt_nextId();
};
arraycls.prototype = new ($rt_objcls())();
arraycls.prototype.constructor = arraycls;
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false, superclass : $rt_objcls() };
cls.$array = arraycls;
}
return cls.$array;
}
$rt_createcls = function() {
return {
$meta : {
supertypes : []
}
};
}
$rt_booleanclsCache = null;
$rt_booleancls = function() {
if ($rt_booleanclsCache == null) {
$rt_booleanclsCache = $rt_createcls();
$rt_booleanclsCache.primitive = true;
$rt_booleanclsCache.name = "boolean";
}
return $rt_booleanclsCache;
}
$rt_charclsCache = null;
$rt_charcls = function() {
if ($rt_charclsCache == null) {
$rt_charclsCache = $rt_createcls();
$rt_charclsCache.primitive = true;
$rt_charclsCache.name = "char";
}
return $rt_charclsCache;
}
$rt_byteclsCache = null;
$rt_bytecls = function() {
if ($rt_byteclsCache == null) {
$rt_byteclsCache = $rt_createcls();
$rt_byteclsCache.primitive = true;
$rt_byteclsCache.name = "byte";
}
return $rt_byteclsCache;
}
$rt_shortclsCache = null;
$rt_shortcls = function() {
if ($rt_shortclsCache == null) {
$rt_shortclsCache = $rt_createcls();
$rt_shortclsCache.primitive = true;
$rt_shortclsCache.name = "short";
}
return $rt_shortclsCache;
}
$rt_intclsCache = null;
$rt_intcls = function() {
if ($rt_intclsCache === null) {
$rt_intclsCache = $rt_createcls();
$rt_intclsCache.primitive = true;
$rt_intclsCache.name = "int";
}
return $rt_intclsCache;
}
$rt_longclsCache = null;
$rt_longcls = function() {
if ($rt_longclsCache === null) {
$rt_longclsCache = $rt_createcls();
$rt_longclsCache.primitive = true;
$rt_longclsCache.name = "long";
}
return $rt_longclsCache;
}
$rt_floatclsCache = null;
$rt_floatcls = function() {
if ($rt_floatclsCache === null) {
$rt_floatclsCache = $rt_createcls();
$rt_floatclsCache.primitive = true;
$rt_floatclsCache.name = "float";
}
return $rt_floatclsCache;
}
$rt_doubleclsCache = null;
$rt_doublecls = function() {
if ($rt_doubleclsCache === null) {
$rt_doubleclsCache = $rt_createcls();
$rt_doubleclsCache.primitive = true;
$rt_doubleclsCache.name = "double";
}
return $rt_doubleclsCache;
}
$rt_voidclsCache = null;
$rt_voidcls = function() {
if ($rt_voidclsCache === null) {
$rt_voidclsCache = $rt_createcls();
$rt_voidclsCache.primitive = true;
$rt_voidclsCache.name = "void";
}
return $rt_voidclsCache;
}
$rt_equals = function(a, b) {
if (a === b) {
return true;
}
if (a === null || b === null) {
return false;
}
if (typeof(a) == 'object') {
return a.equals(b);
} else {
return false;
}
}
$rt_clinit = function(cls) {
if (cls.$clinit) {
var f = cls.$clinit;
delete cls.$clinit;
f();
}
return cls;
}
$rt_init = function(cls, constructor, args) {
var obj = new cls();
cls.prototype[constructor].apply(obj, args);
return obj;
}
$rt_throw = function(ex) {
var err = ex.$jsException;
if (!err) {
var err = new Error("Java exception thrown");
err.$javaException = ex;
ex.$jsException = err;
}
throw err;
}
$rt_byteToInt = function(value) {
return value > 0xFF ? value | 0xFFFFFF00 : value;
}
$rt_shortToInt = function(value) {
return value > 0xFFFF ? value | 0xFFFF0000 : value;
}
$rt_createMultiArray = function(cls, dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createArray(cls, firstDim);
}
return $rt_createMultiArrayImpl(cls, arrays, dimensions);
}
$rt_createByteMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createByteArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_bytecls(), arrays, dimensions);
}
$rt_createBooleanMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createBooleanArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_booleancls(), arrays, dimensions);
}
$rt_createShortMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createShortArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_shortcls(), arrays, dimensions);
}
$rt_createIntMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createIntArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_intcls(), arrays, dimensions);
}
$rt_createLongMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createLongArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_longcls(), arrays, dimensions);
}
$rt_createFloatMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createFloatArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_floatcls(), arrays, dimensions);
}
$rt_createDoubleMultiArray = function(dimensions) {
var arrays = new Array($rt_primitiveArrayCount(dimensions));
var firstDim = dimensions[0] | 0;
for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) {
arrays[i] = $rt_createDoubleArray(firstDim);
}
return $rt_createMultiArrayImpl($rt_doublecls(), arrays, dimensions);
}
$rt_primitiveArrayCount = function(dimensions) {
var val = dimensions[1] | 0;
for (var i = 2 | 0; i < dimensions.length; i = (i + 1) | 0) {
val = (val * (dimensions[i] | 0)) | 0;
}
return val;
}
$rt_createMultiArrayImpl = function(cls, arrays, dimensions) {
var limit = arrays.length;
for (var i = 1 | 0; i < dimensions.length; i = (i + 1) | 0) {
cls = $rt_arraycls(cls);
var dim = dimensions[i];
var index = 0;
var packedIndex = 0;
while (index < limit) {
var arr = $rt_createUnfilledArray(cls, dim);
for (var j = 0; j < dim; j = (j + 1) | 0) {
arr.data[j] = arrays[index];
index = (index + 1) | 0;
}
arrays[packedIndex] = arr;
packedIndex = (packedIndex + 1) | 0;
}
limit = packedIndex;
}
return arrays[0];
}
$rt_assertNotNaN = function(value) {
if (typeof value == 'number' && isNaN(value)) {
throw "NaN";
}
return value;
}
$rt_methodStubs = function(clinit, names) {
for (var i = 0; i < names.length; i = (i + 1) | 0) {
window[names[i]] = (function(name) {
return function() {
clinit();
return window[name].apply(window, arguments);
}
})(names[i]);
}
}
$rt_stdoutBuffer = "";
$rt_putStdout = function(ch) {
if (ch === 0xA) {
if (console) {
console.info($rt_stdoutBuffer);
}
$rt_stdoutBuffer = "";
} else {
$rt_stdoutBuffer += String.fromCharCode(ch);
}
}
$rt_stderrBuffer = "";
$rt_putStderr = function(ch) {
if (ch === 0xA) {
if (console) {
console.info($rt_stderrBuffer);
}
$rt_stderrBuffer = "";
} else {
$rt_stderrBuffer += String.fromCharCode(ch);
}
}
function $rt_declClass(cls, data) {
cls.name = data.name;
cls.$meta = {};
cls.$meta.superclass = data.superclass;
cls.$meta.supertypes = data.interfaces ? data.interfaces.slice() : [];
if (data.superclass) {
cls.$meta.supertypes.push(data.superclass);
cls.prototype = new data.superclass();
} else {
cls.prototype = new Object();
}
cls.$meta.name = data.name;
cls.$meta.enum = data.enum;
cls.prototype.constructor = cls;
cls.$clinit = data.clinit;
}
function $rt_virtualMethods(cls) {
for (var i = 1; i < arguments.length; i += 2) {
var name = arguments[i];
var func = arguments[i + 1];
if (typeof name == 'string') {
cls.prototype[name] = func;
} else {
for (var j = 0; j < name.length; ++j) {
cls.prototype[name[j]] = func;
}
}
}
}
Long = function(lo, hi) {
this.lo = lo | 0;
this.hi = hi | 0;
}
Long_ZERO = new Long(0, 0);
Long_fromInt = function(val) {
return val >= 0 ? new Long(val, 0) : new Long(val, -1);
}
Long_fromNumber = function(val) {
return new Long(val | 0, (val / 0x100000000) | 0);
}
Long_toNumber = function(val) {
return val.hi >= 0 ? val.lo + 0x100000000 * val.hi : -0x100000000 * (val.hi ^ 0xFFFFFFFF) + val.lo;
}
Long_add = function(a, b) {
var a_lolo = a.lo & 0xFFFF;
var a_lohi = a.lo >>> 16;
var a_hilo = a.hi & 0xFFFF;
var a_hihi = a.hi >>> 16;
var b_lolo = b.lo & 0xFFFF;
var b_lohi = b.lo >>> 16;
var b_hilo = b.hi & 0xFFFF;
var b_hihi = b.hi >>> 16;
var lolo = (a_lolo + b_lolo) | 0;
var lohi = (a_lohi + b_lohi + (lolo >> 16)) | 0;
var hilo = (a_hilo + b_hilo + (lohi >> 16)) | 0;
var hihi = (a_hihi + b_hihi + (hilo >> 16)) | 0;
return new Long((lolo & 0xFFFF) | ((lohi & 0xFFFF) << 16),
(hilo & 0xFFFF) | ((hihi & 0xFFFF) << 16));
}
Long_inc = function(a) {
var lo = (a.lo + 1) | 0;
var hi = a.hi;
if (lo === 0) {
hi = (hi + 1) | 0;
}
return new Long(lo, hi);
}
Long_dec = function(a) {
var lo = (a.lo - 1) | 0;
var hi = a.hi;
if (lo === -1) {
hi = (hi - 1) | 0;
}
return new Long(lo, hi);
}
Long_neg = function(a) {
return Long_inc(new Long(a.lo ^ 0xFFFFFFFF, a.hi ^ 0xFFFFFFFF));
}
Long_sub = function(a, b) {
var a_lolo = a.lo & 0xFFFF;
var a_lohi = a.lo >>> 16;
var a_hilo = a.hi & 0xFFFF;
var a_hihi = a.hi >>> 16;
var b_lolo = b.lo & 0xFFFF;
var b_lohi = b.lo >>> 16;
var b_hilo = b.hi & 0xFFFF;
var b_hihi = b.hi >>> 16;
var lolo = (a_lolo - b_lolo) | 0;
var lohi = (a_lohi - b_lohi + (lolo >> 16)) | 0;
var hilo = (a_hilo - b_hilo + (lohi >> 16)) | 0;
var hihi = (a_hihi - b_hihi + (hilo >> 16)) | 0;
return new Long((lolo & 0xFFFF) | ((lohi & 0xFFFF) << 16),
(hilo & 0xFFFF) | ((hihi & 0xFFFF) << 16));
}
Long_compare = function(a, b) {
var r = a.hi - b.hi;
if (r !== 0) {
return r;
}
var r = (a.lo >>> 1) - (b.lo >>> 1);
if (r !== 0) {
return r;
}
return (a.lo & 1) - (b.lo & 1);
}
Long_isPositive = function(a) {
return (a.hi & 0x80000000) === 0;
}
Long_isNegative = function(a) {
return (a.hi & 0x80000000) !== 0;
}
Long_mul = function(a, b) {
var positive = Long_isNegative(a) === Long_isNegative(b);
if (Long_isNegative(a)) {
a = Long_neg(a);
}
if (Long_isNegative(b)) {
b = Long_neg(b);
}
var a_lolo = a.lo & 0xFFFF;
var a_lohi = a.lo >>> 16;
var a_hilo = a.hi & 0xFFFF;
var a_hihi = a.hi >>> 16;
var b_lolo = b.lo & 0xFFFF;
var b_lohi = b.lo >>> 16;
var b_hilo = b.hi & 0xFFFF;
var b_hihi = b.hi >>> 16;
var lolo = (a_lolo * b_lolo) | 0;
var lohi = (a_lohi * b_lolo + a_lolo * b_lohi + (lolo >> 16)) | 0;
var hilo = (a_hilo * b_lolo + a_lohi * b_lohi + a_lolo * b_hilo + (lohi >> 16)) | 0;
var hihi = (a_hihi * b_lolo + a_hilo * b_lohi + a_lohi * b_hilo + a_lolo * b_hihi + (hilo >> 16)) | 0;
var result = new Long((lolo & 0xFFFF) | ((lohi & 0xFFFF) << 16), (hilo & 0xFFFF) | ((hihi & 0xFFFF) << 16));
return positive ? result : Long_neg(result);
}
Long_div = function(a, b) {
return Long_divRem(a, b)[0];
}
Long_rem = function(a, b) {
return Long_divRem(a, b)[1];
}
Long_divRem = function(a, b) {
var positive = Long_isNegative(a) === Long_isNegative(b);
if (Long_isNegative(a)) {
a = Long_neg(a);
}
if (Long_isNegative(b)) {
b = Long_neg(b);
}
a = new LongInt(a.lo, a.hi, 0);
b = new LongInt(b.lo, b.hi, 0);
var q = LongInt_div(a, b);
a = new Long(a.lo, a.hi);
q = new Long(q.lo, q.hi);
return positive ? [q, a] : [Long_neg(q), Long_neg(a)];
}
Long_shiftLeft16 = function(a) {
return new Long(a.lo << 16, (a.lo >>> 16) | (a.hi << 16));
}
Long_shiftRight16 = function(a) {
return new Long((a.lo >>> 16) | (a.hi << 16), a.hi >>> 16);
}
Long_and = function(a, b) {
return new Long(a.lo & b.lo, a.hi & b.hi);
}
Long_or = function(a, b) {
return new Long(a.lo | b.lo, a.hi | b.hi);
}
Long_xor = function(a, b) {
return new Long(a.lo ^ b.lo, a.hi ^ b.hi);
}
Long_shl = function(a, b) {
if (b < 32) {
return new Long(a.lo << b, (a.lo >>> (32 - b)) | (a.hi << b));
} else {
return new Long(0, a.lo << (b - 32));
}
}
Long_shr = function(a, b) {
if (b < 32) {
return new Long((a.lo >>> b) | (a.hi << (32 - b)), a.hi >> b);
} else {
return new Long((a.hi >> (b - 32)), -1);
}
}
Long_shru = function(a, b) {
if (b < 32) {
return new Long((a.lo >>> b) | (a.hi << (32 - b)), a.hi >>> b);
} else {
return new Long((a.hi >>> (b - 32)), 0);
}
}
// Represents a mutable 80-bit unsigned integer
LongInt = function(lo, hi, sup) {
this.lo = lo;
this.hi = hi;
this.sup = sup;
}
LongInt_mul = function(a, b) {
var a_lolo = ((a.lo & 0xFFFF) * b) | 0;
var a_lohi = ((a.lo >>> 16) * b) | 0;
var a_hilo = ((a.hi & 0xFFFF) * b) | 0;
var a_hihi = ((a.hi >>> 16) * b) | 0;
var sup = (a.sup * b) | 0;
a_lohi = (a_lohi + (a_lolo >> 16)) | 0;
a_hilo = (a_hilo + (a_lohi >> 16)) | 0;
a_hihi = (a_hihi + (a_hilo >> 16)) | 0;
sup = (sup + (a_hihi >> 16)) | 0;
a.lo = (a_lolo & 0xFFFF) | (a_lohi << 16);
a.hi = (a_hilo & 0xFFFF) | (a_hihi << 16);
a.sup = sup & 0xFFFF;
}
LongInt_sub = function(a, b) {
var a_lolo = a.lo & 0xFFFF;
var a_lohi = a.lo >>> 16;
var a_hilo = a.hi & 0xFFFF;
var a_hihi = a.hi >>> 16;
var b_lolo = b.lo & 0xFFFF;
var b_lohi = b.lo >>> 16;
var b_hilo = b.hi & 0xFFFF;
var b_hihi = b.hi >>> 16;
a_lolo = (a_lolo - b_lolo) | 0;
a_lohi = (a_lohi - b_lohi + (a_lolo >> 16)) | 0;
a_hilo = (a_hilo - b_hilo + (a_lohi >> 16)) | 0;
a_hihi = (a_hihi - b_hihi + (a_hilo >> 16)) | 0;
sup = (a.sup - b.sup + (a_hihi >> 16)) | 0;
a.lo = (a_lolo & 0xFFFF) | ((a_lohi & 0xFFFF) << 16);
a.hi = (a_hilo & 0xFFFF) | ((a_hihi & 0xFFFF) << 16);
a.sup = sup;
}
LongInt_add = function(a, b) {
var a_lolo = a.lo & 0xFFFF;
var a_lohi = a.lo >>> 16;
var a_hilo = a.hi & 0xFFFF;
var a_hihi = a.hi >>> 16;
var b_lolo = b.lo & 0xFFFF;
var b_lohi = b.lo >>> 16;
var b_hilo = b.hi & 0xFFFF;
var b_hihi = b.hi >>> 16;
a_lolo = (a_lolo + b_lolo) | 0;
a_lohi = (a_lohi + b_lohi + (a_lolo >> 16)) | 0;
a_hilo = (a_hilo + b_hilo + (a_lohi >> 16)) | 0;
a_hihi = (a_hihi + b_hihi + (a_hilo >> 16)) | 0;
sup = (a.sup + b.sup + (a_hihi >> 16)) | 0;
a.lo = (a_lolo & 0xFFFF) | (a_lohi << 16);
a.hi = (a_hilo & 0xFFFF) | (a_hihi << 16);
a.sup = sup;
}
LongInt_ucompare = function(a, b) {
var r = (a.sup - b.sup);
if (r != 0) {
return r;
}
var r = (a.hi >>> 1) - (b.hi >>> 1);
if (r != 0) {
return r;
}
var r = (a.hi & 1) - (b.hi & 1);
if (r != 0) {
return r;
}
var r = (a.lo >>> 1) - (b.lo >>> 1);
if (r != 0) {
return r;
}
return (a.lo & 1) - (b.lo & 1);
}
LongInt_numOfLeadingZeroBits = function(a) {
var n = 0;
var d = 16;
while (d > 0) {
if ((a >>> d) !== 0) {
a >>>= d;
n = (n + d) | 0;
}
d = (d / 2) | 0;
}
return 31 - n;
}
LongInt_shl = function(a, b) {
if (b < 32) {
a.sup = ((a.hi >>> (32 - b)) | (a.sup << b)) & 0xFFFF;
a.hi = (a.lo >>> (32 - b)) | (a.hi << b);
a.lo <<= b;
} else if (b < 64) {
a.sup = ((a.lo >>> (64 - b)) | (a.hi << (b - 32))) & 0xFFFF;
a.hi = a.lo << b;
a.lo = 0;
} else {
a.sup = (a.lo << (b - 64)) & 0xFFFF;
a.hi = 0;
a.lo = 0;
}
}
LongInt_shr = function(a, b) {
if (b < 32) {
a.lo = (a.lo >>> b) | (a.hi << (32 - b));
a.hi = (a.hi >>> b) | (a.sup << (32 - b));
a.sup >>>= b;
} else if (b < 64) {
a.lo = (a.hi >>> (b - 32)) | (a.sup << (64 - b));
a.hi = a.sup >>> (b - 32);
a.sup = 0;
} else {
a.lo = a.sup >>> (b - 64);
a.hi = 0;
a.sup = 0;
}
}
LongInt_copy = function(a) {
return new LongInt(a.lo, a.hi, a.sup);
}
LongInt_div = function(a, b) {
// Normalize divisor
var bits = b.hi !== 0 ? LongInt_numOfLeadingZeroBits(b.hi) : LongInt_numOfLeadingZeroBits(b.lo) + 32;
var sz = 1 + ((bits / 16) | 0);
var dividentBits = bits % 16;
LongInt_shl(b, bits);
LongInt_shl(a, dividentBits);
q = new LongInt(0, 0, 0);
while (sz-- > 0) {
LongInt_shl(q, 16);
// Calculate approximate q
var digitA = (a.hi >>> 16) + (0x10000 * a.sup);
var digitB = b.hi >>> 16;
var digit = (digitA / digitB) | 0;
var t = LongInt_copy(b);
LongInt_mul(t, digit);
// Adjust q either down or up
if (LongInt_ucompare(t, a) >= 0) {
while (LongInt_ucompare(t, a) > 0) {
LongInt_sub(t, b);
q = (q - 1) | 0;
}
} else {
while (true) {
var nextT = LongInt_copy(t);
LongInt_add(nextT, b);
if (LongInt_ucompare(nextT, a) > 0) {
break;
}
t = nextT;
q = (q + 1) | 0;
}
}
LongInt_sub(a, t);
q.lo |= digit;
LongInt_shl(a, 16);
}
LongInt_shr(a, bits + 16);
return q;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B