runsunspider.js revision 842:75e8d1a4ba23
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * runsunspider : runs the sunspider tests and checks for compliance 26 * 27 * @test 28 * @option -timezone=PST 29 * @runif external.sunspider 30 */ 31 32/** 33 * This is not a test, but a test "framework" for running sunspider tests. 34 */ 35 36function assertEq(a, b) { 37 if (a !== b) { 38 throw "ASSERTION FAILED: " + a + " should be " + b; 39 } 40} 41 42function pprint(x) { 43 if (verbose_run) { 44 print(x); 45 } 46} 47 48var runs = 0; 49var total_time = 0; 50 51function runbench(name) { 52 var filename = name.split("/").pop(); 53 pprint("Running (warmup/sanity) " + filename); 54 55 var start = new Date; 56 load(name); 57 var stop = new Date - start; 58 total_time += stop; 59 60 pprint(filename + " done in " + stop + " ms"); 61 runs++; 62} 63 64var m_w; 65var m_z; 66var MAXINT; 67 68//produce deterministic random numbers for test suite 69function pseudorandom() { 70 m_z = 36969 * (m_z & 65535) + (m_z >> 16); 71 m_w = 18000 * (m_w & 65535) + (m_w >> 16); 72 return (Math.abs((m_z << 16) + m_w) & MAXINT) / MAXINT; 73} 74 75function initrandom() { 76 m_w = 4711; 77 m_z = 17; 78 MAXINT = 0x7fffffff; 79 Math.random = pseudorandom; 80} 81 82var rtimes = 0; 83var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__; 84var single; 85var verbose_run = false; 86 87var args = []; 88if (typeof $ARGS !== 'undefined') { 89 args = $ARGS; 90} else if (typeof arguments !== 'undefined' && arguments.length != 0) { 91 args = arguments; 92} 93 94for (var i = 0; i < args.length; i++) { 95 if (args[i] === '--verbose') { 96 verbose_run = true; 97 } else if (args[i] === '--times') { 98 i++; 99 rtimes = +args[i]; 100 } else if (args[i] === '--single') { 101 i++; 102 single = args[i]; 103 } 104} 105 106function runsuite(tests) { 107 var changed = false; 108 var res = []; 109 var oldRandom = Math.random; 110 111 try { 112 for (var n = 0; n < tests.length; n++) { 113 path = dir + '../external/sunspider/tests/sunspider-1.0.2/' + tests[n].name 114 115 initrandom(); 116 117 var dd = new Date; 118 119 runbench(path); 120 if (typeof tests[n].actual !== 'undefined') { 121 assertEq(tests[n].actual(), tests[n].expected()); 122 } 123 124 if (typeof tests[n].rerun !== 'undefined' && tests[n].times > 0) { 125 pprint("rerunning " + tests[n].name + " " + tests[n].times + " times..."); 126 var times = 0; 127 var to = tests[n].times; 128 129 var elemsPerPercent = to / 100; 130 var po = 0|(to / 10); 131 132 times = 0; 133 for (; times < to; times++) { 134 initrandom(); 135 tests[n].rerun(); 136 if ((times % (po|0)) == 0) { 137 pprint(times/to * 100 + "%"); 138 } 139 } 140 } 141 142 var t = new Date - dd; 143 pprint("time: " + t + " ms"); 144 if (typeof tests[n].actual !== 'undefined') { 145 assertEq(tests[n].actual(), tests[n].expected()); 146 } 147 res.push(t); 148 149 pprint(""); 150 151 changed = true; 152 } 153 } catch (e) { 154 print("FAIL!"); 155 throw e; 156 // no scripting or something, silently fail 157 } finally { 158 Math.random = oldRandom; 159 } 160 161 for (var n = 0; n < tests.length; n++) { 162 163 var time = "" + res[n]; 164 while (time.length < 4) { 165 time = " " + time; 166 } 167 time += " ms"; 168 if (res[n] == -1) { 169 time = "<couldn't be rerun>"; 170 } 171 var str = tests[n].name; 172 for (var spaces = str.length; spaces < 32; spaces++) { 173 str += " "; 174 } 175 str += " "; 176 str += time; 177 178 if (tests[n].times > 0) { 179 str += " ["; 180 str += tests[n].times + " reruns]"; 181 } 182 pprint(str); 183 } 184 185 return changed; 186} 187 188function hash(str) { 189 var s = "" + str; 190 var h = 0; 191 var off = 0; 192 for (var i = 0; i < s.length; i++) { 193 h = 31 * h + s.charCodeAt(off++); 194 h &= 0x7fffffff; 195 } 196 return h ^ s.length; 197} 198 199var tests = [ 200 201 { name: 'regexp-dna.js', 202 actual: function() { 203 return dnaOutputString + dnaInput; 204 }, 205 expected: function() { 206 return expectedDNAOutputString + expectedDNAInput; 207 }, 208 }, 209 210 { name: 'string-base64.js', 211 actual: function() { 212 return hash(str); 213 }, 214 expected: function() { 215 return 1544571068; 216 }, 217 times: rtimes, 218 rerun: function() { 219 toBinaryTable = [ 220 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, 221 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, 222 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, 223 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, 224 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 225 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, 226 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 227 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 228 ]; 229 var str = ""; 230 for (var i = 0; i < 8192; i++) 231 str += String.fromCharCode((25 * Math.random()) + 97); 232 233 for (var i = 8192; i <= 16384; i *= 2) { 234 var base64; 235 base64 = toBase64(str); 236 var encoded = base64ToString(base64); 237 238 str += str; 239 } 240 toBinaryTable = null; 241 } 242 }, 243 { name: 'date-format-xparb.js', 244 actual: function() { 245 return shortFormat + longFormat; 246 }, 247 expected: function() { 248 return "2017-09-05Tuesday, September 05, 2017 8:43:48 AM"; 249 }, 250 times: rtimes, 251 rerun: function() { 252 date = new Date("1/1/2007 1:11:11"); 253 for (i = 0; i < 4000; ++i) { 254 var shortFormat = date.dateFormat("Y-m-d"); 255 var longFormat = date.dateFormat("l, F d, Y g:i:s A"); 256 date.setTime(date.getTime() + 84266956); 257 } 258 } 259 260 }, 261 { name: 'string-validate-input.js', 262 actual: function() { 263 return hash(endResult); 264 }, 265 expected: function() { 266 return 726038055; 267 }, 268 times: rtimes, 269 rerun: function() { 270 doTest(); 271 }, 272 }, 273 { name: '3d-morph.js', 274 actual: function() { 275 var acceptableDelta = 4e-15; 276 return (testOutput - 6.394884621840902e-14) < acceptableDelta; 277 }, 278 expected: function() { 279 return true; 280 }, 281 times: rtimes, 282 rerun: function() { 283 a = Array() 284 for (var i=0; i < nx*nz*3; ++i) 285 a[i] = 0 286 for (var i = 0; i < loops; ++i) { 287 morph(a, i/loops) 288 } 289 testOutput = 0; 290 for (var i = 0; i < nx; i++) 291 testOutput += a[3*(i*nx+i)+1]; 292 a = null; 293 294 } 295 }, 296 { name: 'crypto-aes.js', 297 actual: function() { 298 return plainText; 299 }, 300 expected: function() { 301 return decryptedText; 302 }, 303 times: rtimes, 304 rerun: function() { 305 cipherText = AESEncryptCtr(plainText, password, 256); 306 decryptedText = AESDecryptCtr(cipherText, password, 256); 307 308 } 309 }, 310 { name: 'crypto-md5.js', 311 actual: function() { 312 return md5Output; 313 }, 314 expected: function() { 315 return "a831e91e0f70eddcb70dc61c6f82f6cd"; 316 }, 317 times: rtimes, 318 rerun: function() { 319 md5Output = hex_md5(plainText); 320 } 321 }, 322 323 { name: 'crypto-sha1.js', 324 actual: function() { 325 return sha1Output; 326 }, 327 expected: function() { 328 return "2524d264def74cce2498bf112bedf00e6c0b796d"; 329 }, 330 times: rtimes, 331 rerun: function() { 332 sha1Output = hex_sha1(plainText); 333 } 334 }, 335 336 { name: 'bitops-bitwise-and.js', 337 actual: function() { 338 return result; 339 }, 340 expected: function() { 341 return 0; 342 }, 343 times: rtimes, 344 rerun: function() { 345 bitwiseAndValue = 4294967296; 346 for (var i = 0; i < 600000; i++) { 347 bitwiseAndValue = bitwiseAndValue & i; 348 } 349 result = bitwiseAndValue; 350 } 351 }, 352 353 { name: 'bitops-bits-in-byte.js', 354 actual: function() { 355 return result; 356 }, 357 expected: function() { 358 return 358400; 359 }, 360 times: rtimes, 361 rerun: function() { 362 result = TimeFunc(bitsinbyte); 363 } 364 }, 365 366 { name: 'bitops-nsieve-bits.js', 367 actual: function() { 368 var ret = 0; 369 for (var i = 0; i < result.length; ++i) { 370 ret += result[i]; 371 } 372 ret += result.length; 373 return ret; 374 }, 375 expected: function() { 376 return -1286749539853; 377 }, 378 times: rtimes, 379 rerun: function() { 380 result = sieve(); 381 } 382 }, 383 384 { name: 'bitops-3bit-bits-in-byte.js', 385 actual: function() { 386 return sum; 387 }, 388 expected: function() { 389 return 512000; 390 }, 391 times: rtimes, 392 rerun: function() { 393 sum = TimeFunc(fast3bitlookup); 394 } 395 }, 396 397 { name: 'access-nbody.js', 398 actual: function() { 399 return ret; 400 }, 401 expected: function() { 402 return -1.3524862408537381; 403 }, 404 times: rtimes, 405 rerun: function() { 406 var ret = 0; 407 for (var n = 3; n <= 24; n *= 2) { 408 (function(){ 409 var bodies = new NBodySystem( Array( 410 Sun(),Jupiter(),Saturn(),Uranus(),Neptune() 411 )); 412 var max = n * 100; 413 414 ret += bodies.energy(); 415 for (var i=0; i<max; i++){ 416 bodies.advance(0.01); 417 } 418 ret += bodies.energy(); 419 })(); 420 } 421 } 422 }, 423 424 { name: 'access-binary-trees.js', 425 actual: function() { 426 return ret; 427 }, 428 expected: function() { 429 return -4; 430 }, 431 times: rtimes, 432 rerun: function() { 433 ret = 0; 434 435 for (var n = 4; n <= 7; n += 1) { 436 var minDepth = 4; 437 var maxDepth = Math.max(minDepth + 2, n); 438 var stretchDepth = maxDepth + 1; 439 440 var check = bottomUpTree(0,stretchDepth).itemCheck(); 441 442 var longLivedTree = bottomUpTree(0,maxDepth); 443 for (var depth=minDepth; depth<=maxDepth; depth+=2){ 444 var iterations = 1 << (maxDepth - depth + minDepth); 445 446 check = 0; 447 for (var i=1; i<=iterations; i++){ 448 check += bottomUpTree(i,depth).itemCheck(); 449 check += bottomUpTree(-i,depth).itemCheck(); 450 } 451 } 452 453 ret += longLivedTree.itemCheck(); 454 } 455 } 456 }, 457 458 { name: 'access-fannkuch.js', 459 actual: function() { 460 return ret; 461 }, 462 expected: function() { 463 return 22; 464 }, 465 times: rtimes, 466 rerun: function() { 467 n = 8; 468 ret = fannkuch(n); 469 } 470 }, 471 472 { name: 'math-spectral-norm.js', 473 actual: function() { 474 var ret = ''; 475 for (var i = 6; i <= 48; i *= 2) { 476 ret += spectralnorm(i) + ','; 477 } 478 return ret; 479 }, 480 expected: function() { 481 return "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,"; 482 }, 483 times: rtimes, 484 rerun: function() { 485 total = 0; 486 for (var i = 6; i <= 48; i *= 2) { 487 total += spectralnorm(i); 488 } 489 } 490 }, 491 492 { name: '3d-raytrace.js', 493 actual: function() { 494 return hash(testOutput); 495 }, 496 expected: function() { 497 return 230692593; 498 }, 499 times: rtimes, 500 rerun: function() { 501 testOutput = arrayToCanvasCommands(raytraceScene()); 502 } 503 }, 504 505 { name: 'math-cordic.js', 506 actual: function() { 507 return total; 508 }, 509 expected: function() { 510 return 10362.570468755888; 511 }, 512 times: rtimes, 513 rerun: function() { 514 total = 0; 515 cordic(25000); 516 } 517 }, 518 519 { name: 'controlflow-recursive.js', 520 actual: function() { 521 var ret = 0; 522 for (var i = 3; i <= 5; i++) { 523 ret += ack(3,i); 524 ret += fib(17.0+i); 525 ret += tak(3*i+3,2*i+2,i+1); 526 } 527 return ret; 528 }, 529 expected: function() { 530 return 57775; 531 }, 532 times: rtimes, 533 rerun: function() { 534 result = 0; 535 for (var i = 3; i <= 5; i++) { 536 result += ack(3,i); 537 result += fib(17.0+i); 538 result += tak(3*i+3,2*i+2,i+1); 539 } 540 } 541 }, 542 543 { name: 'date-format-tofte.js', 544 actual: function() { 545 return shortFormat + longFormat; 546 }, 547 expected: function() { 548 return "2008-05-01Thursday, May 01, 2008 6:31:22 PM"; 549 }, 550 times: rtimes, 551 rerun: function() { 552 date = new Date("1/1/2007 1:11:11"); 553 for (i = 0; i < 500; ++i) { 554 var shortFormat = date.formatDate("Y-m-d"); 555 var longFormat = date.formatDate("l, F d, Y g:i:s A"); 556 date.setTime(date.getTime() + 84266956); 557 } 558 } 559 }, 560 561 { name: 'string-tagcloud.js', 562 actual: function() { 563 // The result string embeds floating-point numbers, which can vary a bit on different platforms, 564 // so we truncate them a bit before comparing. 565 var tagcloud_norm = tagcloud.replace(/([0-9.]+)px/g, function(str, p1) { return p1.substr(0, 10) + 'px' }) 566 return tagcloud_norm.length; 567 }, 568 expected: function() { 569 return 295906; 570 }, 571 times: rtimes, 572 rerun: function() { 573 tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } }); 574 tagcloud = makeTagCloud(tagInfo); 575 } 576 }, 577 578 { name: 'math-partial-sums.js', 579 actual: function() { 580 return total; 581 }, 582 expected: function() { 583 return 60.08994194659945; 584 }, 585 times: rtimes, 586 rerun: function() { 587 total = 0; 588 for (var i = 1024; i <= 16384; i *= 2) { 589 total += partial(i); 590 } 591 } 592 }, 593 594 { name: 'access-nsieve.js', 595 actual: function() { 596 return result; 597 }, 598 expected: function() { 599 return 14302; 600 }, 601 times: rtimes, 602 rerun: function() { 603 result = sieve(); 604 } 605 }, 606 607 { name: '3d-cube.js', 608 times: rtimes, 609 rerun: function() { 610 Q = new Array(); 611 MTrans = new Array(); // transformation matrix 612 MQube = new Array(); // position information of qube 613 I = new Array(); // entity matrix 614 Origin = new Object(); 615 Testing = new Object(); 616 for ( var i = 20; i <= 160; i *= 2 ) { 617 Init(i); 618 } 619 } 620 }, 621 622 //TODO no easy way to sanity check result 623 { name: 'string-fasta.js', 624 times: rtimes, 625 rerun: function() { 626 ret = 0; 627 count = 7; 628 fastaRepeat(2*count*100000, ALU); 629 fastaRandom(3*count*1000, IUB); 630 fastaRandom(5*count*1000, HomoSap); 631 } 632 }, 633 634 //TODO no easy way to sanity check result 635 { name: 'string-unpack-code.js', 636 actual: function() { 637 return decompressedMochiKit.length == 106415 && 638 decompressedMochiKit[2000] == '5' && 639 decompressedMochiKit[12000] == '_' && 640 decompressedMochiKit[82556] == '>'; 641 }, 642 expected: function() { 643 return true; 644 }, 645 }, 646 647]; 648 649tests.sort(function(a,b) { return a.name.localeCompare(b.name); }); 650if (typeof single !== 'undefined') { 651 for (i in tests) { 652 if (tests[i].name === single) { 653 singleTest = tests[i]; 654 tests = [singleTest]; 655 break; 656 } 657 } 658 if (tests.length != 1) { 659 throw "unknown single test '" + single + "'"; 660 } 661} 662 663 664// handle the case this script may be run by a JS engine that doesn't 665// support __DIR__ global variable. 666 667runsuite(tests); 668 669pprint('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms "); 670 671print("Sunspider finished!"); 672