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