64fd9c191a
Reviewed-by: hannesw, lagergren
685 lines
16 KiB
JavaScript
685 lines
16 KiB
JavaScript
/*
|
|
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/**
|
|
* runsunspider : runs the sunspider tests and checks for compliance
|
|
*
|
|
* @test
|
|
* @option -timezone=PST
|
|
* @runif external.sunspider
|
|
*/
|
|
|
|
/**
|
|
* This is not a test, but a test "framework" for running sunspider tests.
|
|
*/
|
|
|
|
function assertEq(a, b) {
|
|
if (a !== b) {
|
|
throw "ASSERTION FAILED: " + a + " should be " + b;
|
|
}
|
|
}
|
|
|
|
function pprint(x) {
|
|
if (verbose_run) {
|
|
print(x);
|
|
}
|
|
}
|
|
|
|
var runs = 0;
|
|
var total_time = 0;
|
|
|
|
function runbench(name) {
|
|
var filename = name.split("/").pop();
|
|
pprint("Running (warmup/sanity) " + filename);
|
|
|
|
var start = new Date;
|
|
load(name);
|
|
|
|
var stop = new Date - start;
|
|
total_time += stop;
|
|
|
|
pprint(filename + " done in " + stop + " ms");
|
|
runs++;
|
|
}
|
|
|
|
var m_w;
|
|
var m_z;
|
|
var MAXINT;
|
|
|
|
//produce deterministic random numbers for test suite
|
|
function pseudorandom() {
|
|
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
|
|
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
|
|
return (Math.abs((m_z << 16) + m_w) & MAXINT) / MAXINT;
|
|
}
|
|
|
|
function initrandom() {
|
|
m_w = 4711;
|
|
m_z = 17;
|
|
MAXINT = 0x7fffffff;
|
|
Math.random = pseudorandom;
|
|
}
|
|
|
|
var rtimes = 0;
|
|
var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
|
|
var single;
|
|
var verbose_run = false;
|
|
var runall = false;
|
|
|
|
var args = [];
|
|
if (typeof $ARGS !== 'undefined') {
|
|
args = $ARGS;
|
|
} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
|
|
args = arguments;
|
|
}
|
|
|
|
for (var i = 0; i < args.length; i++) {
|
|
if (args[i] === '--verbose') {
|
|
verbose_run = true;
|
|
} else if (args[i] === '--times') {
|
|
i++;
|
|
rtimes = +args[i];
|
|
} else if (args[i] === '--single') {
|
|
i++;
|
|
single = args[i];
|
|
} else if (args[i] === '--runall') {
|
|
i++;
|
|
runall = true;
|
|
}
|
|
}
|
|
|
|
function runsuite(tests) {
|
|
var changed = false;
|
|
var res = [];
|
|
var oldRandom = Math.random;
|
|
|
|
try {
|
|
for (var n = 0; n < tests.length; n++) {
|
|
try {
|
|
path = dir + '../external/sunspider/tests/sunspider-1.0.2/' + tests[n].name
|
|
|
|
initrandom();
|
|
|
|
var dd = new Date;
|
|
|
|
runbench(path);
|
|
if (typeof tests[n].actual !== 'undefined') {
|
|
assertEq(tests[n].actual(), tests[n].expected());
|
|
}
|
|
|
|
if (typeof tests[n].rerun !== 'undefined' && tests[n].times > 0) {
|
|
pprint("rerunning " + tests[n].name + " " + tests[n].times + " times...");
|
|
var times = 0;
|
|
var to = tests[n].times;
|
|
|
|
var elemsPerPercent = to / 100;
|
|
var po = 0|(to / 10);
|
|
|
|
times = 0;
|
|
for (; times < to; times++) {
|
|
initrandom();
|
|
tests[n].rerun();
|
|
if ((times % (po|0)) == 0) {
|
|
pprint(times/to * 100 + "%");
|
|
}
|
|
}
|
|
}
|
|
|
|
var t = new Date - dd;
|
|
pprint("time: " + t + " ms");
|
|
if (typeof tests[n].actual !== 'undefined') {
|
|
assertEq(tests[n].actual(), tests[n].expected());
|
|
}
|
|
res.push(t);
|
|
|
|
pprint("");
|
|
|
|
changed = true;
|
|
} catch(e) {
|
|
if(runall) {
|
|
print("FAIL!");
|
|
} else {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
print("FAIL!");
|
|
throw e;
|
|
// no scripting or something, silently fail
|
|
} finally {
|
|
Math.random = oldRandom;
|
|
}
|
|
|
|
for (var n = 0; n < tests.length; n++) {
|
|
|
|
var time = "" + res[n];
|
|
while (time.length < 4) {
|
|
time = " " + time;
|
|
}
|
|
time += " ms";
|
|
if (res[n] == -1) {
|
|
time = "<couldn't be rerun>";
|
|
}
|
|
var str = tests[n].name;
|
|
for (var spaces = str.length; spaces < 32; spaces++) {
|
|
str += " ";
|
|
}
|
|
str += " ";
|
|
str += time;
|
|
|
|
if (tests[n].times > 0) {
|
|
str += " [";
|
|
str += tests[n].times + " reruns]";
|
|
}
|
|
pprint(str);
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
function hash(str) {
|
|
var s = "" + str;
|
|
var h = 0;
|
|
var off = 0;
|
|
for (var i = 0; i < s.length; i++) {
|
|
h = 31 * h + s.charCodeAt(off++);
|
|
h &= 0x7fffffff;
|
|
}
|
|
return h ^ s.length;
|
|
}
|
|
|
|
var tests = [
|
|
|
|
{ name: 'regexp-dna.js',
|
|
actual: function() {
|
|
return dnaOutputString + dnaInput;
|
|
},
|
|
expected: function() {
|
|
return expectedDNAOutputString + expectedDNAInput;
|
|
},
|
|
},
|
|
|
|
{ name: 'string-base64.js',
|
|
actual: function() {
|
|
return hash(str);
|
|
},
|
|
expected: function() {
|
|
return 1544571068;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
toBinaryTable = [
|
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
|
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
|
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
|
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
|
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
|
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
|
];
|
|
var str = "";
|
|
for (var i = 0; i < 8192; i++)
|
|
str += String.fromCharCode((25 * Math.random()) + 97);
|
|
|
|
for (var i = 8192; i <= 16384; i *= 2) {
|
|
var base64;
|
|
base64 = toBase64(str);
|
|
var encoded = base64ToString(base64);
|
|
|
|
str += str;
|
|
}
|
|
toBinaryTable = null;
|
|
}
|
|
},
|
|
{ name: 'date-format-xparb.js',
|
|
actual: function() {
|
|
return shortFormat + longFormat;
|
|
},
|
|
expected: function() {
|
|
return "2017-09-05Tuesday, September 05, 2017 8:43:48 AM";
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
date = new Date("1/1/2007 1:11:11");
|
|
for (i = 0; i < 4000; ++i) {
|
|
var shortFormat = date.dateFormat("Y-m-d");
|
|
var longFormat = date.dateFormat("l, F d, Y g:i:s A");
|
|
date.setTime(date.getTime() + 84266956);
|
|
}
|
|
}
|
|
|
|
},
|
|
{ name: 'string-validate-input.js',
|
|
actual: function() {
|
|
return hash(endResult);
|
|
},
|
|
expected: function() {
|
|
return 726038055;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
doTest();
|
|
},
|
|
},
|
|
{ name: '3d-morph.js',
|
|
actual: function() {
|
|
var acceptableDelta = 4e-15;
|
|
return (testOutput - 6.394884621840902e-14) < acceptableDelta;
|
|
},
|
|
expected: function() {
|
|
return true;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
a = Array()
|
|
for (var i=0; i < nx*nz*3; ++i)
|
|
a[i] = 0
|
|
for (var i = 0; i < loops; ++i) {
|
|
morph(a, i/loops)
|
|
}
|
|
testOutput = 0;
|
|
for (var i = 0; i < nx; i++)
|
|
testOutput += a[3*(i*nx+i)+1];
|
|
a = null;
|
|
|
|
}
|
|
},
|
|
{ name: 'crypto-aes.js',
|
|
actual: function() {
|
|
return plainText;
|
|
},
|
|
expected: function() {
|
|
return decryptedText;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
cipherText = AESEncryptCtr(plainText, password, 256);
|
|
decryptedText = AESDecryptCtr(cipherText, password, 256);
|
|
|
|
}
|
|
},
|
|
{ name: 'crypto-md5.js',
|
|
actual: function() {
|
|
return md5Output;
|
|
},
|
|
expected: function() {
|
|
return "a831e91e0f70eddcb70dc61c6f82f6cd";
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
md5Output = hex_md5(plainText);
|
|
}
|
|
},
|
|
|
|
{ name: 'crypto-sha1.js',
|
|
actual: function() {
|
|
return sha1Output;
|
|
},
|
|
expected: function() {
|
|
return "2524d264def74cce2498bf112bedf00e6c0b796d";
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
sha1Output = hex_sha1(plainText);
|
|
}
|
|
},
|
|
|
|
{ name: 'bitops-bitwise-and.js',
|
|
actual: function() {
|
|
return result;
|
|
},
|
|
expected: function() {
|
|
return 0;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
bitwiseAndValue = 4294967296;
|
|
for (var i = 0; i < 600000; i++) {
|
|
bitwiseAndValue = bitwiseAndValue & i;
|
|
}
|
|
result = bitwiseAndValue;
|
|
}
|
|
},
|
|
|
|
{ name: 'bitops-bits-in-byte.js',
|
|
actual: function() {
|
|
return result;
|
|
},
|
|
expected: function() {
|
|
return 358400;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
result = TimeFunc(bitsinbyte);
|
|
}
|
|
},
|
|
|
|
{ name: 'bitops-nsieve-bits.js',
|
|
actual: function() {
|
|
var ret = 0;
|
|
for (var i = 0; i < result.length; ++i) {
|
|
ret += result[i];
|
|
}
|
|
ret += result.length;
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return -1286749539853;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
result = sieve();
|
|
}
|
|
},
|
|
|
|
{ name: 'bitops-3bit-bits-in-byte.js',
|
|
actual: function() {
|
|
return sum;
|
|
},
|
|
expected: function() {
|
|
return 512000;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
sum = TimeFunc(fast3bitlookup);
|
|
}
|
|
},
|
|
|
|
{ name: 'access-nbody.js',
|
|
actual: function() {
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return -1.3524862408537381;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
var ret = 0;
|
|
for (var n = 3; n <= 24; n *= 2) {
|
|
(function(){
|
|
var bodies = new NBodySystem( Array(
|
|
Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
|
|
));
|
|
var max = n * 100;
|
|
|
|
ret += bodies.energy();
|
|
for (var i=0; i<max; i++){
|
|
bodies.advance(0.01);
|
|
}
|
|
ret += bodies.energy();
|
|
})();
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: 'access-binary-trees.js',
|
|
actual: function() {
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return -4;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
ret = 0;
|
|
|
|
for (var n = 4; n <= 7; n += 1) {
|
|
var minDepth = 4;
|
|
var maxDepth = Math.max(minDepth + 2, n);
|
|
var stretchDepth = maxDepth + 1;
|
|
|
|
var check = bottomUpTree(0,stretchDepth).itemCheck();
|
|
|
|
var longLivedTree = bottomUpTree(0,maxDepth);
|
|
for (var depth=minDepth; depth<=maxDepth; depth+=2){
|
|
var iterations = 1 << (maxDepth - depth + minDepth);
|
|
|
|
check = 0;
|
|
for (var i=1; i<=iterations; i++){
|
|
check += bottomUpTree(i,depth).itemCheck();
|
|
check += bottomUpTree(-i,depth).itemCheck();
|
|
}
|
|
}
|
|
|
|
ret += longLivedTree.itemCheck();
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: 'access-fannkuch.js',
|
|
actual: function() {
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return 22;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
n = 8;
|
|
ret = fannkuch(n);
|
|
}
|
|
},
|
|
|
|
{ name: 'math-spectral-norm.js',
|
|
actual: function() {
|
|
var ret = '';
|
|
for (var i = 6; i <= 48; i *= 2) {
|
|
ret += spectralnorm(i) + ',';
|
|
}
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,";
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
total = 0;
|
|
for (var i = 6; i <= 48; i *= 2) {
|
|
total += spectralnorm(i);
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: '3d-raytrace.js',
|
|
actual: function() {
|
|
return hash(testOutput);
|
|
},
|
|
expected: function() {
|
|
return 230692593;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
testOutput = arrayToCanvasCommands(raytraceScene());
|
|
}
|
|
},
|
|
|
|
{ name: 'math-cordic.js',
|
|
actual: function() {
|
|
return total;
|
|
},
|
|
expected: function() {
|
|
return 10362.570468755888;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
total = 0;
|
|
cordic(25000);
|
|
}
|
|
},
|
|
|
|
{ name: 'controlflow-recursive.js',
|
|
actual: function() {
|
|
var ret = 0;
|
|
for (var i = 3; i <= 5; i++) {
|
|
ret += ack(3,i);
|
|
ret += fib(17.0+i);
|
|
ret += tak(3*i+3,2*i+2,i+1);
|
|
}
|
|
return ret;
|
|
},
|
|
expected: function() {
|
|
return 57775;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
result = 0;
|
|
for (var i = 3; i <= 5; i++) {
|
|
result += ack(3,i);
|
|
result += fib(17.0+i);
|
|
result += tak(3*i+3,2*i+2,i+1);
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: 'date-format-tofte.js',
|
|
actual: function() {
|
|
return shortFormat + longFormat;
|
|
},
|
|
expected: function() {
|
|
return "2008-05-01Thursday, May 01, 2008 6:31:22 PM";
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
date = new Date("1/1/2007 1:11:11");
|
|
for (i = 0; i < 500; ++i) {
|
|
var shortFormat = date.formatDate("Y-m-d");
|
|
var longFormat = date.formatDate("l, F d, Y g:i:s A");
|
|
date.setTime(date.getTime() + 84266956);
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: 'string-tagcloud.js',
|
|
actual: function() {
|
|
// The result string embeds floating-point numbers, which can vary a bit on different platforms,
|
|
// so we truncate them a bit before comparing.
|
|
var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' })
|
|
return tagcloud_norm.length;
|
|
},
|
|
expected: function() {
|
|
return 295906;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } });
|
|
tagcloud = makeTagCloud(tagInfo);
|
|
}
|
|
},
|
|
|
|
{ name: 'math-partial-sums.js',
|
|
actual: function() {
|
|
return total;
|
|
},
|
|
expected: function() {
|
|
return 60.08994194659945;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
total = 0;
|
|
for (var i = 1024; i <= 16384; i *= 2) {
|
|
total += partial(i);
|
|
}
|
|
}
|
|
},
|
|
|
|
{ name: 'access-nsieve.js',
|
|
actual: function() {
|
|
return result;
|
|
},
|
|
expected: function() {
|
|
return 14302;
|
|
},
|
|
times: rtimes,
|
|
rerun: function() {
|
|
result = sieve();
|
|
}
|
|
},
|
|
|
|
{ name: '3d-cube.js',
|
|
times: rtimes,
|
|
rerun: function() {
|
|
Q = new Array();
|
|
MTrans = new Array(); // transformation matrix
|
|
MQube = new Array(); // position information of qube
|
|
I = new Array(); // entity matrix
|
|
Origin = new Object();
|
|
Testing = new Object();
|
|
for ( var i = 20; i <= 160; i *= 2 ) {
|
|
Init(i);
|
|
}
|
|
}
|
|
},
|
|
|
|
//TODO no easy way to sanity check result
|
|
{ name: 'string-fasta.js',
|
|
times: rtimes,
|
|
rerun: function() {
|
|
ret = 0;
|
|
count = 7;
|
|
fastaRepeat(2*count*100000, ALU);
|
|
fastaRandom(3*count*1000, IUB);
|
|
fastaRandom(5*count*1000, HomoSap);
|
|
}
|
|
},
|
|
|
|
//TODO no easy way to sanity check result
|
|
{ name: 'string-unpack-code.js',
|
|
actual: function() {
|
|
return decompressedMochiKit.length == 106415 &&
|
|
decompressedMochiKit[2000] == '5' &&
|
|
decompressedMochiKit[12000] == '_' &&
|
|
decompressedMochiKit[82556] == '>';
|
|
},
|
|
expected: function() {
|
|
return true;
|
|
},
|
|
},
|
|
|
|
];
|
|
|
|
tests.sort(function(a,b) { return a.name.localeCompare(b.name); });
|
|
if (typeof single !== 'undefined') {
|
|
for (i in tests) {
|
|
if (tests[i].name === single) {
|
|
singleTest = tests[i];
|
|
tests = [singleTest];
|
|
break;
|
|
}
|
|
}
|
|
if (tests.length != 1) {
|
|
throw "unknown single test '" + single + "'";
|
|
}
|
|
}
|
|
|
|
|
|
// handle the case this script may be run by a JS engine that doesn't
|
|
// support __DIR__ global variable.
|
|
|
|
runsuite(tests);
|
|
|
|
pprint('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms ");
|
|
|
|
print("Sunspider finished!");
|