webgl-conformance-tests.html (38896B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 <!DOCTYPE html> 7 <html> 8 <head> 9 <meta charset="utf-8"> 10 <!-- Prevents Chrome from offering to translate tests which generate 11 random characters for things like attribute names --> 12 <meta name="google" value="notranslate"> 13 <meta name="viewport" content="width=device-width"> 14 <title>WebGL Conformance Tests</title> 15 <style> 16 * { 17 box-sizing: border-box; 18 } 19 20 body { 21 border: 0; 22 margin: 0; 23 padding: 0; 24 height: 100%; 25 max-height:100%; 26 font-family: Verdana, Arial, sans-serif; 27 font-size: 0.8em; 28 } 29 30 input[type=button], select { 31 padding: 2px 6px 2px 6px; 32 margin: 0; 33 border: 1px solid #888; 34 border-radius: 2px; 35 background: #f4f4f4; 36 } 37 38 a { 39 color: #88F; 40 text-decoration: none; 41 } 42 43 a:hover { 44 border-bottom: 1px solid #66D; 45 } 46 47 label { 48 white-space: nowrap; 49 } 50 51 #testlist { 52 position:fixed; 53 top:180px; 54 left:0; 55 right: calc(10% + 50px); 56 bottom:0px; 57 overflow:auto; 58 min-height: 200px; 59 } 60 61 @media screen and (max-width: 500px) { 62 #testlist { 63 font-size: 80%; 64 } 65 } 66 67 #header { 68 position:absolute; 69 top:0; 70 left:0; 71 width:100%; 72 height: 160px; 73 overflow: scroll; 74 border-bottom: 1px solid #CCC; 75 } 76 77 #info { 78 margin: 0 auto; 79 max-width: 280px; 80 } 81 #logo { 82 width: 68px; 83 height: 40px; 84 } 85 86 #iframe-container { 87 color: white; 88 display: block; 89 position: fixed; 90 width: 90%; 91 height: calc(100% - 170px); 92 bottom: 0px; 93 left: calc(90% - 50px); 94 transition: left 0.15s; 95 } 96 #iframe-container.iframe-shown { 97 left: 10%; 98 } 99 #iframe-toggle { 100 display: inline-block; 101 vertical-align: middle; 102 width: 20px; 103 height: 100%; 104 padding: 0; 105 -webkit-appearance: none; 106 } 107 #test-iframe { 108 display: inline-block; 109 vertical-align: middle; 110 background: white; 111 width: calc(100% - 20px); 112 height: 100%; 113 border: 1px solid black; 114 } 115 116 .folder { 117 margin-bottom: 1.5em; 118 } 119 120 .folderHeader { 121 white-space: nowrap; 122 position: sticky; 123 top: 0; 124 } 125 .folderHeaderInner { 126 background: white; 127 /* to hide checkboxes from parent headers */ 128 position: relative; 129 left: -2em; 130 padding-left: 2em; 131 } 132 133 .folderName { 134 font-weight: bold; 135 } 136 137 .folderMessage { 138 margin-left: 1em; 139 font-size: 0.9em; 140 } 141 142 .pageHeader { 143 white-space: nowrap; 144 } 145 146 .testpage { 147 border-style: solid; 148 border-color: #CCC; 149 border-width: 0px 0 1px 0; 150 background-color: #FFF; 151 padding: 4px 0 4px 0; 152 153 -webkit-transition: background-color 0.25s; 154 -moz-transition: background-color 0.25s; 155 transition: background-color 0.25s; 156 } 157 158 .testpage:first-child { 159 border-width: 1px 0 1px 0; 160 } 161 162 .timeout { } 163 .success { } 164 .fail { } 165 .testpagesuccess { background-color: #8F8; } 166 .testpagefail { background-color: #F88; } 167 .testpageskipped { background-color: #888; } 168 .testpagetimeout { background-color: #FC8; } 169 .nowebgl { font-weight: bold; color: red; } 170 #error-wrap { 171 float: left; 172 position: relative; 173 left: 50%; 174 } 175 #error { 176 color: red; 177 float: left; 178 position: relative; 179 left: -50%; 180 text-align: left; 181 } 182 ul { 183 list-style: none; 184 padding-left: 1em; 185 } 186 </style> 187 <script type="application/javascript" src="js/webgl-test-harness.js"></script> 188 <script> 189 "use strict"; 190 191 window.onbeforeunload = function() { 192 // Prompt user before reloading 193 return false; 194 } 195 196 var DEFAULT_CONFORMANCE_TEST_VERSION = "2.0.1 (beta)"; 197 198 var OPTIONS = { 199 version: DEFAULT_CONFORMANCE_TEST_VERSION, 200 frames: 1, 201 allowSkip: 0, 202 root: null, 203 quiet: 0 204 }; 205 206 var testVersions = [ 207 "1.0.4 (beta)", 208 "2.0.1 (beta)" 209 ]; 210 211 function start() { 212 213 function log(msg) { 214 if (window.console && window.console.log) { 215 window.console.log(msg); 216 } 217 } 218 219 function createStylesheet() { 220 var style = document.createElement("style"); 221 style.appendChild(document.createTextNode("")); 222 document.head.appendChild(style); 223 return style.sheet; 224 } 225 226 function create3DContext(canvas, attrs, version) { 227 if (!canvas) { 228 canvas = document.createElement("canvas"); 229 } 230 var context = null; 231 var names; 232 switch (version) { 233 case 2: 234 names = ["webgl2"]; break; 235 default: 236 names = ["webgl", "experimental-webgl"]; break; 237 } 238 for (var i = 0; i < names.length; ++i) { 239 try { 240 context = canvas.getContext(names[i], attrs); 241 } catch (e) { 242 } 243 if (context) { 244 break; 245 } 246 } 247 return context; 248 } 249 250 var reportType = WebGLTestHarnessModule.TestHarness.reportType; 251 var pageCount = 0; 252 var folderCount = 0; 253 var autoScrollEnabled = true; // Whether the user prefers to auto scroll 254 var autoScroll = true; // Whether auto scroll is actually performed 255 let quickTestMode = true; 256 257 var Page = function(reporter, folder, testIndex, url) { 258 this.reporter = reporter; 259 this.folder = folder; 260 this.url = url; 261 this.totalTests = 0; 262 this.totalSuccessful = 0; 263 this.totalTimeouts = 0; 264 this.totalSkipped = 0; 265 this.totalFailed = 0; 266 this.testIndex = testIndex; 267 this.startTime = new Date(); 268 this.totalTime = 0; 269 var that = this; 270 271 this.elementId = "page" + pageCount++; 272 var li = reporter.localDoc.createElement('li'); 273 li.id = this.elementId; 274 var div = reporter.localDoc.createElement('div'); 275 div.classList.add('pageHeader'); 276 var check = reporter.localDoc.createElement('input'); 277 check.type = 'checkbox'; 278 check.checked = true; 279 check.onclick = function() { 280 if (this.checked) { 281 that.folder.enableUp_(); 282 } 283 else { 284 that.folder.disableUp_(); 285 } 286 }; 287 div.appendChild(check); 288 var button = reporter.localDoc.createElement('input'); 289 button.type = 'button'; 290 button.id = this.elementId + "-button"; 291 button.value = 'run'; 292 button.onclick = function() { 293 autoScroll = false; 294 reporter.runTest(url); 295 }; 296 if (reporter.noSelectedWebGLVersion) { 297 button.disabled = true; 298 } 299 div.appendChild(button); 300 var a = reporter.localDoc.createElement('a'); 301 a.href = WebGLTestHarnessModule.getURLWithOptions(url, { 302 webglVersion: reporter.selectedWebGLVersion, 303 quiet: OPTIONS.quiet, 304 quick: quickTestMode ? 1 : 0, 305 }); 306 a.target = "_blank"; 307 const folderName = that.folder.displayName; 308 console.assert(folderName.startsWith("all/")); 309 console.assert(url.startsWith(folderName.substring(4) + "/")); 310 const urlWithoutFolder = url.substring(folderName.length - 4 + 1); 311 var node = reporter.localDoc.createTextNode(urlWithoutFolder); 312 a.appendChild(node); 313 div.appendChild(a); 314 li.setAttribute('class', 'testpage'); 315 li.appendChild(div); 316 var ul = reporter.localDoc.createElement('ul'); 317 var node = reporter.localDoc.createTextNode(''); 318 li.appendChild(ul); 319 div.appendChild(node); 320 this.totalsElem = node; 321 this.resultElem = ul; 322 this.elem = li; 323 this.check = check; 324 }; 325 326 Page.prototype.checked = function() { 327 return this.check.checked; 328 } 329 330 Page.prototype.addResult = function(msg, success, skipped) { 331 ++this.totalTests; 332 if (success === undefined) { 333 ++this.totalTimeouts; 334 var result = "timeout"; 335 var css = "timeout"; 336 } else if (success) { 337 ++this.totalSuccessful; 338 // don't report success. 339 return; 340 } else { 341 ++this.totalFailed; 342 if (skipped) { 343 // Skipped tests are counted as both skips and failures (because we 344 // don't want to accidentally accept a conformance submission with 345 // skipped tests). 346 ++this.totalSkipped; 347 } 348 var result = "failed"; 349 var css = "fail"; 350 } 351 352 var node = this.reporter.localDoc.createTextNode(result + ': ' + msg); 353 var li = this.reporter.localDoc.createElement('li'); 354 li.appendChild(node); 355 li.setAttribute('class', css); 356 this.resultElem.appendChild(li); 357 }; 358 359 Page.prototype.startPage = function() { 360 if (autoScroll && this.elem.scrollIntoView) { 361 this.elem.scrollIntoView(false); 362 } 363 this.totalTests = 0; 364 this.totalSuccessful = 0; 365 this.totalSkipped = 0; 366 this.totalFailed = 0; 367 this.totalTimeouts = 0; 368 this.totalTime = 0; 369 // remove previous results. 370 while (this.resultElem.hasChildNodes()) { 371 this.resultElem.removeChild(this.resultElem.childNodes[0]); 372 } 373 this.totalsElem.textContent = ''; 374 375 var shouldRun = this.check.checked && this.folder.checked(); 376 377 if (shouldRun) { 378 this.elem.classList.remove('testpagetimeout'); 379 this.elem.classList.remove('testpageskipped'); 380 this.elem.classList.remove('testpagefail'); 381 this.elem.classList.remove('testpagesuccess'); 382 this.startTime = Date.now(); 383 } 384 385 return this.check.checked && this.folder.checked(); 386 }; 387 388 Page.prototype.firstTestIndex = function() { 389 return this.testIndex; 390 }; 391 392 Page.prototype.finishPage = function(success) { 393 var shouldRun = this.check.checked && this.folder.checked(); 394 if (shouldRun) { 395 this.totalTime = Date.now() - this.startTime; 396 } else { 397 this.totalTime = 0; 398 } 399 400 var passedMsg = ' (Passed: ' + this.totalSuccessful + '/' + this.totalTests; 401 var skippedMsg = ''; 402 if (this.totalSkipped > 0) { 403 skippedMsg = ' Skipped: ' + this.totalSkipped + '/' + this.totalTests; 404 } 405 var failedMsg = ''; 406 if (this.totalFailed > 0) { 407 failedMsg = ' Failed: ' + this.totalFailed + '/' + this.totalTests; 408 } 409 var timeoutMsg = ''; 410 if (this.totalTimeouts > 0) { 411 timeoutMsg = ' Timeout: ' + this.totalTimeouts + '/' + this.totalTests; 412 } 413 var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg + ' in ' + this.totalTime.toFixed(1) + ' ms)'; 414 415 if (success === undefined) { 416 var css = 'testpagetimeout'; 417 msg = '(*timeout*)'; 418 ++this.totalTests; 419 ++this.totalTimeouts; 420 } else if (this.totalSkipped) { 421 var css = 'testpageskipped'; 422 } else if (this.totalSuccessful != this.totalTests) { 423 var css = 'testpagefail'; 424 } else { 425 var css = 'testpagesuccess'; 426 } 427 this.elem.classList.add(css); 428 this.totalsElem.textContent = msg; 429 this.folder.pageFinished(this, success); 430 }; 431 432 Page.prototype.enableTest = function(re) { 433 if (this.url.match(re)) { 434 this.check.checked = true; 435 this.folder.enableUp_(); 436 } 437 }; 438 439 Page.prototype.disableTest = function(re) { 440 if (this.url.match(re)) { 441 this.check.checked = false; 442 } 443 }; 444 445 Page.prototype.toJSON = function() { 446 return { 447 'subtests': this.totalTests, 448 'successful': this.totalSuccessful, 449 'skipped': this.totalSkipped, 450 'failed': this.totalFailed, 451 'timedOut': this.totalTimeouts, 452 'totalTime': this.totalTime, 453 }; 454 }; 455 456 457 var Folder = function(reporter, folder, depth, opt_name) { 458 this.reporter = reporter; 459 this.depth = depth; 460 this.name = opt_name || ""; 461 this.displayName = this.name; 462 if (folder && folder.displayName) { 463 this.displayName = folder.displayName + '/' + this.displayName; 464 } 465 this.subFolders = {}; 466 this.pages = []; 467 this.items = []; 468 this.folder = folder; 469 this.cachedTotalTime = 0; 470 this.cachedTotalSuccessful = 0; 471 this.cachedTotalSkipped = 0; 472 this.cachedTotalTimeouts = 0; 473 this.cachedTotalTests = 0; 474 var that = this; 475 476 var doc = reporter.localDoc; 477 this.elementId = "folder" + folderCount++; 478 var li = doc.createElement('li'); 479 li.id = this.elementId; 480 li.classList.add("folder"); 481 var folderHeader = doc.createElement('div'); 482 folderHeader.classList.add('folderHeader'); 483 var folderHeaderInner = doc.createElement('div'); 484 folderHeaderInner.classList.add('folderHeaderInner'); 485 folderHeader.appendChild(folderHeaderInner); 486 var check = doc.createElement('input'); 487 check.type = 'checkbox'; 488 check.checked = true; 489 check.onclick = function() { 490 if (this.checked) { 491 that.enableTest(".*"); 492 } 493 else { 494 that.disableTest(".*", true); 495 } 496 }; 497 folderHeaderInner.appendChild(check); 498 var button = doc.createElement('input'); 499 button.type = 'button'; 500 button.value = 'run'; 501 button.onclick = function() { 502 autoScroll = autoScrollEnabled; 503 that.run(); 504 }; 505 if (reporter.noSelectedWebGLVersion) { 506 button.disabled = true; 507 } 508 folderHeaderInner.appendChild(button); 509 var h = doc.createElement('span'); 510 h.classList.add('folderName'); 511 h.appendChild(doc.createTextNode(this.displayName)); 512 folderHeaderInner.appendChild(h); 513 var m = doc.createElement('span'); 514 m.classList.add('folderMessage'); 515 this.msgNode = doc.createTextNode(''); 516 m.appendChild(this.msgNode); 517 folderHeaderInner.appendChild(m); 518 var ul = doc.createElement('ul'); 519 li.appendChild(folderHeader); 520 li.appendChild(ul); 521 this.childUL = ul; 522 this.elem = li; 523 this.check = check; 524 this.folderHeader = folderHeader; 525 }; 526 527 Folder.prototype.checked = function() { 528 return this.check.checked && 529 (this.folder ? this.folder.checked() : true); 530 }; 531 532 Folder.prototype.firstTestIndex = function() { 533 return this.items[0].firstTestIndex(); 534 }; 535 536 Folder.prototype.numChildren = function() { 537 var numChildren = 0; 538 for (var name in this.subFolders) { 539 numChildren += this.subFolders[name].numChildren(); 540 } 541 return numChildren + this.pages.length; 542 }; 543 544 Folder.prototype.totalTime = function() { 545 // Check to see if the cached total time needs to be recomputed 546 if (this.cachedTotalTime == -1) { 547 this.cachedTotalTime = 0; 548 for (var name in this.subFolders) { 549 this.cachedTotalTime += this.subFolders[name].totalTime(); 550 } 551 for (var ii = 0; ii < this.pages.length; ++ii) { 552 this.cachedTotalTime += this.pages[ii].totalTime; 553 } 554 } 555 return this.cachedTotalTime; 556 }; 557 558 Folder.prototype.totalSuccessful = function() { 559 if (this.cachedTotalSuccessful == -1) { 560 this.cachedTotalSuccessful = 0; 561 for (var name in this.subFolders) { 562 this.cachedTotalSuccessful += this.subFolders[name].totalSuccessful(); 563 } 564 for (var ii = 0; ii < this.pages.length; ++ii) { 565 this.cachedTotalSuccessful += this.pages[ii].totalSuccessful; 566 } 567 } 568 return this.cachedTotalSuccessful; 569 }; 570 571 Folder.prototype.totalSkipped = function() { 572 if (this.cachedTotalSkipped == -1) { 573 this.cachedTotalSkipped = 0; 574 for (var name in this.subFolders) { 575 this.cachedTotalSkipped += this.subFolders[name].totalSkipped(); 576 } 577 for (var ii = 0; ii < this.pages.length; ++ii) { 578 this.cachedTotalSkipped += this.pages[ii].totalSkipped; 579 } 580 } 581 return this.cachedTotalSkipped; 582 }; 583 584 Folder.prototype.totalFailed = function() { 585 if (this.cachedTotalFailed == -1) { 586 this.cachedTotalFailed = 0; 587 for (var name in this.subFolders) { 588 this.cachedTotalFailed += this.subFolders[name].totalFailed(); 589 } 590 for (var ii = 0; ii < this.pages.length; ++ii) { 591 this.cachedTotalFailed += this.pages[ii].totalFailed; 592 } 593 } 594 return this.cachedTotalFailed; 595 }; 596 597 Folder.prototype.totalTimeouts = function() { 598 if (this.cachedTotalTimeouts == -1) { 599 this.cachedTotalTimeouts = 0; 600 for (var name in this.subFolders) { 601 this.cachedTotalTimeouts += this.subFolders[name].totalTimeouts(); 602 } 603 for (var ii = 0; ii < this.pages.length; ++ii) { 604 this.cachedTotalTimeouts += this.pages[ii].totalTimeouts; 605 } 606 } 607 return this.cachedTotalTimeouts; 608 }; 609 610 Folder.prototype.totalTests = function() { 611 if (this.cachedTotalTests == -1) { 612 this.cachedTotalTests = 0; 613 for (var name in this.subFolders) { 614 this.cachedTotalTests += this.subFolders[name].totalTests(); 615 } 616 for (var ii = 0; ii < this.pages.length; ++ii) { 617 this.cachedTotalTests += this.pages[ii].totalTests; 618 } 619 } 620 return this.cachedTotalTests; 621 }; 622 623 Folder.prototype.run = function() { 624 this.msgNode.textContent = ''; 625 var firstTestIndex = this.firstTestIndex(); 626 var count = this.numChildren(); 627 log("run tests: " + firstTestIndex + " to " + (firstTestIndex + count - 1)) 628 testHarness.runTests({start: firstTestIndex, count: count}); 629 }; 630 631 Folder.prototype.pageFinished = function(page, success) { 632 this.cachedTotalTime = -1; 633 this.cachedTotalSuccessful = -1; 634 this.cachedTotalSkipped = -1; 635 this.cachedTotalFailed = -1; 636 this.cachedTotalTimeouts = -1; 637 this.cachedTotalTests = -1; 638 var passedMsg = ' (Passed: ' + this.totalSuccessful() + '/' + this.totalTests(); 639 var skippedMsg = ''; 640 if (this.totalSkipped() > 0) { 641 skippedMsg = ' Skipped: ' + this.totalSkipped() + '/' + this.totalTests(); 642 } 643 var failedMsg = ''; 644 if (this.totalFailed() > 0) { 645 failedMsg = ' Failed: ' + this.totalFailed() + '/' + this.totalTests(); 646 } 647 var timeoutMsg = ''; 648 if (this.totalTimeouts() > 0) { 649 timeoutMsg = ' Timeout: ' + this.totalTimeouts() + '/' + this.totalTests(); 650 } 651 this.msgNode.textContent = passedMsg + skippedMsg + failedMsg + timeoutMsg + ' in ' + (this.totalTime() / 1000).toFixed(2) + ' seconds)'; 652 if (this.folder) { 653 this.folder.pageFinished(page, success); 654 } 655 }; 656 657 Folder.prototype.getSubFolder = function(name) { 658 var subFolder = this.subFolders[name]; 659 if (subFolder === undefined) { 660 subFolder = new Folder(this.reporter, this, this.depth + 1, name); 661 this.subFolders[name] = subFolder; 662 this.items.push(subFolder); 663 this.childUL.appendChild(subFolder.elem); 664 } 665 return subFolder; 666 }; 667 668 Folder.prototype.getOrCreateFolder = function(url) { 669 var parts = url.split('/'); 670 var folder = this; 671 for (var pp = 0; pp < parts.length - 1; ++pp) { 672 folder = folder.getSubFolder(parts[pp]); 673 } 674 return folder; 675 }; 676 677 Folder.prototype.addPage = function(page) { 678 this.pages.push(page); 679 this.items.push(page); 680 this.childUL.appendChild(page.elem); 681 this.folderHeader.classList.add('hasPages'); 682 }; 683 684 Folder.prototype.disableTest = function(re, opt_forceRecurse) { 685 var recurse = true; 686 if (this.name.match(re)) { 687 this.check.checked = false; 688 recurse = opt_forceRecurse; 689 } 690 if (recurse) { 691 for (var name in this.subFolders) { 692 this.subFolders[name].disableTest(re, opt_forceRecurse); 693 } 694 for (var ii = 0; ii < this.pages.length; ++ii) { 695 this.pages[ii].disableTest(re); 696 } 697 } 698 }; 699 700 Folder.prototype.enableUp_ = function() { 701 this.check.checked = true; 702 var parent = this.folder; 703 if (parent) { 704 parent.enableUp_(); 705 } 706 } 707 708 Folder.prototype.disableUp_ = function() { 709 var checked = false; 710 for (var name in this.subFolders) { 711 checked = this.subFolders[name].checked(); 712 if (checked) { 713 break; 714 } 715 } 716 for (var ii = 0; ii < this.pages.length && checked == false; ++ii) { 717 checked = this.pages[ii].checked(); 718 } 719 this.check.checked = checked; 720 var parent = this.folder; 721 if (parent) { 722 parent.disableUp_(); 723 } 724 } 725 726 Folder.prototype.enableTest = function(re) { 727 if (this.name.match(re)) { 728 this.enableUp_(); 729 } 730 for (var name in this.subFolders) { 731 this.subFolders[name].enableTest(re); 732 } 733 for (var ii = 0; ii < this.pages.length; ++ii) { 734 this.pages[ii].enableTest(re); 735 } 736 }; 737 738 var Reporter = function(iframes) { 739 this.localDoc = document; 740 this.resultElem = document.getElementById("results"); 741 this.fullResultsElem = document.getElementById("fullresults"); 742 var node = this.localDoc.createTextNode(''); 743 this.fullResultsElem.appendChild(node); 744 this.fullResultsNode = node; 745 this.iframes = iframes; 746 this.currentPageElem = null; 747 this.totalPages = 0; 748 this.pagesByURL = {}; 749 750 // Check to see if WebGL is supported 751 var canvas = document.createElement("canvas"); 752 var ctx = create3DContext(canvas, null, 1); 753 754 // Check to see if WebGL2 is supported 755 var canvas2 = document.createElement("canvas"); 756 var ctx2 = create3DContext(canvas2, null, 2); 757 758 this.noSelectedWebGLVersion = false; 759 this.selectedWebGLVersion = WebGLTestHarnessModule.getMajorVersion(OPTIONS.version); 760 if (this.selectedWebGLVersion == 2 && !ctx2) { 761 this.noSelectedWebGLVersion = true; 762 } else if (this.selectedWebGLVersion == 1 && !ctx) { 763 this.noSelectedWebGLVersion = true; 764 } 765 766 // If the WebGL2 context could be created use it to get context info 767 if (ctx2) { 768 ctx = ctx2; 769 } 770 771 this.noWebGL = !ctx; 772 773 this.contextInfo = {}; 774 this.root = new Folder(this, null, 0, "all"); 775 this.resultElem.appendChild(this.root.elem); 776 this.callbacks = { }; 777 this.startTime = new Date(); 778 779 if (ctx) { 780 this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR); 781 this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION); 782 this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER); 783 this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS); 784 this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS); 785 this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS); 786 this.contextInfo["ALPHA_BITS"] = ctx.getParameter(ctx.ALPHA_BITS); 787 this.contextInfo["DEPTH_BITS"] = ctx.getParameter(ctx.DEPTH_BITS); 788 this.contextInfo["STENCIL_BITS"] = ctx.getParameter(ctx.STENCIL_BITS); 789 790 var ext = ctx.getExtension("WEBGL_debug_renderer_info"); 791 if (ext) { 792 this.contextInfo["UNMASKED_VENDOR"] = ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL); 793 this.contextInfo["UNMASKED_RENDERER"] = ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL); 794 } 795 } 796 }; 797 798 Reporter.prototype.enableTest = function(name) { 799 this.root.enableTest(name); 800 }; 801 802 Reporter.prototype.disableTest = function(name) { 803 this.root.disableTest(name); 804 }; 805 806 Reporter.prototype.disableAllTests = function() { 807 this.root.disableTest(".*", true); 808 }; 809 810 Reporter.prototype.addEventListener = function(type, func) { 811 if (!this.callbacks[type]) { 812 this.callbacks[type] = []; 813 } 814 this.callbacks[type].push(func); 815 }; 816 817 Reporter.prototype.executeListenerEvents_ = function(type) { 818 var callbacks = this.callbacks[type].slice(0); 819 for (var ii = 0; ii < callbacks.length; ++ii) { 820 setTimeout(callbacks[ii], 0); 821 } 822 }; 823 824 Reporter.prototype.runTest = function(url) { 825 var page = this.pagesByURL[url]; 826 testHarness.runTests({start: page.firstTestIndex(), count: 1}); 827 }; 828 829 Reporter.prototype.getFolder = function(url) { 830 return this.root.getOrCreateFolder(url); 831 }; 832 833 Reporter.prototype.addPage = function(url) { 834 var folder = this.getFolder(url); 835 var page = new Page(this, folder, this.totalPages, url); 836 folder.addPage(page); 837 ++this.totalPages; 838 this.pagesByURL[url] = page; 839 }; 840 841 Reporter.prototype.startPage = function(url) { 842 var page = this.pagesByURL[url]; 843 return page.startPage(); 844 }; 845 846 Reporter.prototype.addResult = function(url, msg, success, skipped) { 847 var page = this.pagesByURL[url]; 848 page.addResult(msg, success, skipped); 849 }; 850 851 Reporter.prototype.finishPage = function(url, success) { 852 var page = this.pagesByURL[url]; 853 page.finishPage(success); 854 if (OPTIONS.dumpShaders == 1) { 855 var xhr = new XMLHttpRequest(); 856 xhr.open('POST', "/finishIndividualTest", true); 857 xhr.send(null); 858 } 859 }; 860 861 Reporter.prototype.displayFinalResults = function(msg, success) { 862 if (success) { 863 var totalTests = 0; 864 var testsSucceeded = 0; 865 var testsFailed = 0; 866 var testsSkipped = 0; 867 var testsTimedOut = 0; 868 869 var subtestsHit = 0; 870 var subtestsSucceeded = 0; 871 var subtestsTimedOut = 0; 872 var subtestsSkipped = 0; 873 var subtestsFailed = 0; 874 875 var totalTime = Date.now() - this.startTime; 876 877 for (var url in this.pagesByURL) { 878 var page = this.pagesByURL[url]; 879 totalTests += 1; 880 if (page.totalSkipped) { 881 testsSkipped += 1; 882 } 883 if (page.totalFailed) { 884 testsFailed += 1; 885 } else if (page.totalTimeouts) { 886 testsTimedOut += 1; 887 } else if (page.totalSuccessful) { 888 if (page.totalSuccessful != page.totalTests) 889 throw successes_not_equal_total; 890 testsSucceeded += 1; 891 } 892 893 subtestsHit += page.totalTests; 894 subtestsSucceeded += page.totalSuccessful; 895 subtestsTimedOut += page.totalTimeouts; 896 subtestsSkipped += page.totalSkipped; 897 subtestsFailed += page.totalFailed; 898 } 899 900 function ratio_str(x, y, name) { 901 return x + '/' + y + ' ' + name + ' (' + (x / y * 100).toFixed(2) + '%)'; 902 } 903 var testsSucceededRatio = ratio_str(testsSucceeded, totalTests, 'tests'); 904 var passedMsg = 'Passed ' + testsSucceededRatio + ', ' + 905 ratio_str(subtestsSucceeded, subtestsHit, 'subtests'); 906 var skippedMsg = ''; 907 if (testsSkipped > 0) { 908 skippedMsg = ' Skipped ' + ratio_str(testsSkipped, totalTests, 'tests'); 909 } 910 var failedMsg = ''; 911 if (testsFailed > 0) { 912 failedMsg = ' Failed ' + ratio_str(testsFailed, totalTests, 'tests') + ', ' + 913 ratio_str(subtestsFailed, subtestsHit, 'subtests'); 914 } 915 var timeoutMsg = ''; 916 if (testsTimedOut > 0) { 917 timeoutMsg = ' Timeout ' + ratio_str(testsTimedOut, totalTests, 'tests'); 918 } 919 var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg; 920 this.fullResultsNode.textContent = msg; 921 922 // generate a text summary 923 var tx = ""; 924 tx += "WebGL Conformance Test Results\n"; 925 tx += "Version " + OPTIONS.version + "\n"; 926 tx += "Generated on: " + (new Date()).toString() + "\n"; 927 tx += "\n"; 928 tx += "-------------------\n\n"; 929 tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n"; 930 tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n"; 931 tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n"; 932 tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n"; 933 tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n"; 934 tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n"; 935 tx += "WebGL R/G/B/A/Depth/Stencil bits (default config): " + this.contextInfo["RED_BITS"] + "/" + this.contextInfo["GREEN_BITS"] + "/" + this.contextInfo["BLUE_BITS"] + "/" + this.contextInfo["ALPHA_BITS"] + "/" + this.contextInfo["DEPTH_BITS"] + "/" + this.contextInfo["STENCIL_BITS"] + "\n"; 936 tx += "\n-------------------\n\n"; 937 938 var result; 939 if (totalTests && testsSucceeded == totalTests) { 940 result = 'PASS'; 941 } else { 942 result = 'FAIL'; 943 } 944 tx += "Test Summary: " + result + " (" + totalTests + " tests):\n"; 945 tx += subtestsHit + " subtests ran in " + (totalTime / 1000.0).toFixed(2) + " seconds\n"; 946 function record(what, tests, subtests) { 947 tx += what + ": " + tests + " tests, " + subtests + " subtests\n"; 948 } 949 record('PASSED', testsSucceeded, subtestsSucceeded); 950 record('NOT PASSED', totalTests - testsSucceeded, subtestsHit - subtestsSucceeded); 951 952 record('FAILED', testsFailed, subtestsFailed); 953 record('TIMED OUT', testsTimedOut, subtestsTimedOut); 954 record('SKIPPED', testsSkipped, subtestsSkipped); 955 956 tx += "\n-------------------\n\n"; 957 958 const failureLines = []; 959 const timeoutLines = []; 960 const resultLines = []; 961 962 for (var url in this.pagesByURL) { 963 var page = this.pagesByURL[url]; 964 resultLines.push(' "' + url + '":' + JSON.stringify(page.toJSON())); 965 966 if (page.totalFailed) { 967 failureLines.push(' "' + url + '",'); 968 } 969 if (page.totalTimeouts) { 970 timeoutLines.push(' "' + url + '",'); 971 } 972 } 973 974 const lines = [].concat( 975 [ 976 '{', 977 ' "failures": [', 978 ], 979 failureLines, 980 [ 981 ' ],', 982 ' "timeouts": [', 983 ], 984 timeoutLines, 985 [ 986 ' ],', 987 ' "results": {', 988 ], 989 resultLines, 990 [ 991 ' },', 992 '}', 993 ] 994 ); 995 996 tx += lines.join('\n'); 997 998 var r = document.getElementById("testResultsAsText"); 999 while (r.firstChild) r.removeChild(r.firstChild); 1000 r.appendChild(document.createTextNode(tx)); 1001 document.getElementById("showTextSummary").disabled = false; 1002 document.getElementById("dlTextSummary").disabled = false; 1003 1004 this.postResultsToServer(tx); 1005 } else { 1006 var e = document.getElementById("error"); 1007 e.innerHTML = msg; 1008 this.postResultsToServer(msg); 1009 } 1010 }; 1011 1012 Reporter.prototype.postTestStartToServer = function(resultText) { 1013 this.startTime = Date.now(); 1014 if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) { 1015 return; 1016 } 1017 1018 var xhr = new XMLHttpRequest(); 1019 xhr.open('POST', "/start", true); 1020 xhr.send(null); 1021 }; 1022 1023 Reporter.prototype.postResultsToServer = function(resultText) { 1024 if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) { 1025 return; 1026 } 1027 1028 var xhr = new XMLHttpRequest(); 1029 xhr.open('POST', "/finish", true); 1030 xhr.setRequestHeader("Content-Type", "text/plain"); 1031 xhr.send(resultText); 1032 }; 1033 1034 Reporter.prototype.ready = function() { 1035 var loading = document.getElementById("loading"); 1036 loading.style.display = "none"; 1037 if (!this.noSelectedWebGLVersion) { 1038 var button = document.getElementById("runTestsButton"); 1039 button.disabled = false; 1040 this.executeListenerEvents_("ready"); 1041 } 1042 }; 1043 1044 Reporter.prototype.reportFunc = function(type, url, msg, success, skipped) { 1045 switch (type) { 1046 case reportType.ADD_PAGE: 1047 return this.addPage(msg); 1048 case reportType.READY: 1049 return this.ready(); 1050 case reportType.START_PAGE: 1051 return this.startPage(url); 1052 case reportType.TEST_RESULT: 1053 return this.addResult(url, msg, success, skipped); 1054 case reportType.FINISH_PAGE: 1055 return this.finishPage(url, success); 1056 case reportType.FINISHED_ALL_TESTS: 1057 return this.displayFinalResults(msg, success); 1058 default: 1059 throw 'unhandled'; 1060 break; 1061 }; 1062 }; 1063 1064 var getURLOptions = function(obj) { 1065 var s = window.location.href; 1066 var q = s.indexOf("?"); 1067 var e = s.indexOf("#"); 1068 if (e < 0) { 1069 e = s.length; 1070 } 1071 var query = s.substring(q + 1, e); 1072 var pairs = query.split("&"); 1073 for (var ii = 0; ii < pairs.length; ++ii) { 1074 var keyValue = pairs[ii].split("="); 1075 var key = keyValue[0]; 1076 var value = decodeURIComponent(keyValue[1]); 1077 obj[key] = value; 1078 } 1079 }; 1080 1081 getURLOptions(OPTIONS); 1082 1083 var makeVersionSelect = function(currentVersion) { 1084 var versionSelect = document.getElementById("testVersion"); 1085 var foundCurrentVersion = false; 1086 var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, ''); 1087 1088 for (var i in testVersions) { 1089 var version = testVersions[i]; 1090 var numericVersion = version.replace(/[^\d.]/g, ''); 1091 var option = document.createElement("option"); 1092 option.setAttribute('value', numericVersion); 1093 option.innerHTML = version; 1094 1095 if (numericVersion == numericCurrentVersion) { 1096 foundCurrentVersion = true; 1097 option.selected = true; 1098 } 1099 1100 versionSelect.appendChild(option); 1101 } 1102 1103 // If the version requested by the query string isn't in the list add it. 1104 if (!foundCurrentVersion) { 1105 var option = document.createElement("option"); 1106 option.setAttribute('value', numericCurrentVersion); 1107 option.innerHTML = currentVersion + " (unknown)"; 1108 option.selected = true; 1109 1110 versionSelect.appendChild(option); 1111 } 1112 1113 versionSelect.addEventListener('change', function(ev) { 1114 window.location.href = "?version=" + versionSelect.value; 1115 }, false); 1116 } 1117 1118 makeVersionSelect(OPTIONS.version); 1119 1120 // Make iframes 1121 var iframes = [document.getElementById("test-iframe")]; 1122 1123 var testPath = "00_test_list.txt"; 1124 if (OPTIONS.root) { 1125 testPath = OPTIONS.root + "/" + testPath; 1126 } 1127 1128 var reporter = new Reporter(iframes); 1129 var testHarness = new WebGLTestHarnessModule.TestHarness( 1130 iframes, 1131 testPath, 1132 function(type, url, msg, success, skipped) { 1133 return reporter.reportFunc(type, url, msg, success, skipped); 1134 }, 1135 OPTIONS); 1136 reporter.addEventListener("ready", function() { 1137 // Set which tests to include. 1138 if (OPTIONS.include) { 1139 reporter.disableAllTests(); 1140 var includes = OPTIONS.include.split(",") 1141 for (var ii = 0; ii < includes.length; ++ii) { 1142 reporter.enableTest(new RegExp(includes[ii])); 1143 } 1144 } 1145 // Remove tests based on skip=re1,re2 in URL. 1146 if (OPTIONS.skip) { 1147 var skips = OPTIONS.skip.split(",") 1148 for (var ii = 0; ii < skips.length; ++ii) { 1149 reporter.disableTest(new RegExp(skips[ii])); 1150 } 1151 } 1152 // Auto run the tests if the run=1 in URL 1153 if (OPTIONS.run != undefined && OPTIONS.run != 0) { 1154 reporter.postTestStartToServer(); 1155 testHarness.runTests(); 1156 } 1157 }); 1158 window.webglTestHarness = testHarness; 1159 var button = document.getElementById("runTestsButton"); 1160 button.disabled = true; 1161 button.onclick = function() { 1162 autoScroll = autoScrollEnabled; 1163 reporter.postTestStartToServer(); 1164 testHarness.runTests(); 1165 }; 1166 var autoScrollCheckbox = document.getElementById("autoScrollCheckbox"); 1167 autoScrollCheckbox.checked = autoScrollEnabled; 1168 autoScrollCheckbox.onclick = function() { 1169 autoScrollEnabled = autoScrollCheckbox.checked; 1170 autoScroll = autoScrollEnabled; 1171 }; 1172 1173 var hidePassedSheet = createStylesheet(); 1174 var hidePassedCheckbox = document.getElementById("hidePassedCheckbox"); 1175 hidePassedCheckbox.checked = false; 1176 hidePassedCheckbox.onclick = function() { 1177 var hidePassedTests = hidePassedCheckbox.checked; 1178 if (hidePassedTests) { 1179 hidePassedSheet.insertRule(".testpagesuccess { display: none; }", 0); 1180 } else { 1181 hidePassedSheet.deleteRule(0); 1182 } 1183 }; 1184 1185 var quickTestModeCheckbox = document.getElementById("quickTestModeCheckbox"); 1186 quickTestModeCheckbox.checked = quickTestMode; 1187 quickTestModeCheckbox.onclick = function() { 1188 quickTestMode = quickTestModeCheckbox.checked; 1189 }; 1190 1191 var textbutton = document.getElementById("showTextSummary"); 1192 textbutton.onclick = function() { 1193 log("click"); 1194 var htmldiv = document.getElementById("testResultsHTML"); 1195 var textdiv = document.getElementById("testResultsText"); 1196 if (textdiv.style.display == "none") { 1197 textdiv.style.display = "block"; 1198 htmldiv.style.display = "none"; 1199 textbutton.setAttribute("value", "display html summary"); 1200 } else { 1201 textdiv.style.display = "none"; 1202 htmldiv.style.display = "block"; 1203 textbutton.setAttribute("value", "display text summary"); 1204 } 1205 }; 1206 1207 function download(filename, text) { 1208 var element = document.createElement("a"); 1209 element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text)); 1210 element.setAttribute("download", filename); 1211 element.style.display = "none"; 1212 document.body.appendChild(element); 1213 element.click(); 1214 document.body.removeChild(element); 1215 } 1216 var dltextbutton = document.getElementById("dlTextSummary"); 1217 dltextbutton.onclick = function() { 1218 var textdiv = document.getElementById("testResultsText"); 1219 download("webgl-conformance-" + OPTIONS.version + ".txt", textdiv.innerText.trim()); 1220 }; 1221 1222 if (reporter.noSelectedWebGLVersion) { 1223 button.disabled = true; 1224 } 1225 if (reporter.noWebGL) { 1226 var elem = document.getElementById("nowebgl"); 1227 elem.style.display = ""; 1228 reporter.postResultsToServer("Browser does not appear to support WebGL"); 1229 } else if (reporter.noSelectedWebGLVersion) { 1230 var elem = document.getElementById("noselectedwebgl"); 1231 elem.style.display = ""; 1232 reporter.postResultsToServer("Browser does not appear to support the selected version of WebGL"); 1233 } 1234 1235 const iframeContainer = document.getElementById("iframe-container"); 1236 const iframeToggle = document.getElementById("iframe-toggle"); 1237 iframeToggle.value = iframeToggle.getAttribute("data-value-hidden"); 1238 iframeToggle.onclick = function() { 1239 const expanded = iframeToggle.myExpanded = !iframeToggle.myExpanded; 1240 if (expanded) { 1241 iframeContainer.classList.add("iframe-shown"); 1242 iframeToggle.value = iframeToggle.getAttribute("data-value-shown"); 1243 } else { 1244 iframeContainer.classList.remove("iframe-shown"); 1245 iframeToggle.value = iframeToggle.getAttribute("data-value-hidden"); 1246 } 1247 }; 1248 } 1249 </script> 1250 </head> 1251 <body onload="start()"> 1252 1253 <div id="testlist"> 1254 <div id="testResultsHTML"> 1255 <ul id="results"> 1256 </ul> 1257 </div> 1258 <div style="display: none;" id="testResultsText"> 1259 <pre id="testResultsAsText"></pre> 1260 </div> 1261 </div> <!-- end of container --> 1262 1263 <div id="iframe-container"> 1264 <input type="button" data-value-hidden="◄" data-value-shown="►" id="iframe-toggle" aria-hidden="true" 1265 ><iframe id="test-iframe"></iframe> 1266 </div> 1267 1268 <div id="header"> 1269 <div id="info"> 1270 <div style="text-align:center"> 1271 <img src="resources/webgl-logo.png" alt="WebGL" id="logo"/> 1272 <br/> 1273 Conformance Test Runner 1274 </div> 1275 Version 1276 <select id="testVersion"> 1277 </select> 1278 <a href="../../conformance-suites/">(older versions?)</a> 1279 <br/> 1280 <input type="button" value="run tests" id="runTestsButton"/> 1281 <label for="autoScrollCheckbox"><input type="checkbox" id="autoScrollCheckbox"/>auto scroll</label> 1282 <label for="hidePassedCheckbox"><input type="checkbox" id="hidePassedCheckbox"/>hide passed</label> 1283 <label for="quickTestModeCheckbox"><input type="checkbox" id="quickTestModeCheckbox"/>quick test mode</label> 1284 <br/> 1285 <input type="button" disabled value="show text summary" id="showTextSummary"/> 1286 <input type="button" disabled value="download text" id="dlTextSummary"/> 1287 <div id="nowebgl" class="nowebgl" style="display: none;"> 1288 This browser does not appear to support WebGL 1289 </div> 1290 <div id="noselectedwebgl" class="nowebgl" style="display: none;"> 1291 This browser does not appear to support the selected version of WebGL 1292 </div> 1293 <div id="loading"> 1294 Loading Tests... 1295 </div> 1296 <div id="fullresults"> 1297 </div> 1298 </div> 1299 <div id="error-wrap"> 1300 <pre id="error"></pre> 1301 </div> 1302 </div> <!-- end of header --> 1303 1304 </body> 1305 </html>