Bug 1933630 - Enable the partial history state update collection on GeckoView session...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / webgl-conformance-tests.html
blob462659227e9b5d42b176e3c1b0344dbe776b64e8
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;
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;
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;
38 a {
39 color: #88F;
40 text-decoration: none;
43 a:hover {
44 border-bottom: 1px solid #66D;
47 label {
48 white-space: nowrap;
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;
61 @media screen and (max-width: 500px) {
62 #testlist {
63 font-size: 80%;
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;
77 #info {
78 margin: 0 auto;
79 max-width: 280px;
81 #logo {
82 width: 68px;
83 height: 40px;
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;
96 #iframe-container.iframe-shown {
97 left: 10%;
99 #iframe-toggle {
100 display: inline-block;
101 vertical-align: middle;
102 width: 20px;
103 height: 100%;
104 padding: 0;
105 -webkit-appearance: none;
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;
116 .folder {
117 margin-bottom: 1.5em;
120 .folderHeader {
121 white-space: nowrap;
122 position: sticky;
123 top: 0;
125 .folderHeaderInner {
126 background: white;
127 /* to hide checkboxes from parent headers */
128 position: relative;
129 left: -2em;
130 padding-left: 2em;
133 .folderName {
134 font-weight: bold;
137 .folderMessage {
138 margin-left: 1em;
139 font-size: 0.9em;
142 .pageHeader {
143 white-space: nowrap;
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;
153 -webkit-transition: background-color 0.25s;
154 -moz-transition: background-color 0.25s;
155 transition: background-color 0.25s;
158 .testpage:first-child {
159 border-width: 1px 0 1px 0;
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%;
175 #error {
176 color: red;
177 float: left;
178 position: relative;
179 left: -50%;
180 text-align: left;
182 ul {
183 list-style: none;
184 padding-left: 1em;
186 </style>
187 <script type="application/javascript" src="js/webgl-test-harness.js"></script>
188 <script>
189 "use strict";
191 window.onbeforeunload = function() {
192 // Prompt user before reloading
193 return false;
196 var DEFAULT_CONFORMANCE_TEST_VERSION = "2.0.1 (beta)";
198 var OPTIONS = {
199 version: DEFAULT_CONFORMANCE_TEST_VERSION,
200 frames: 1,
201 allowSkip: 0,
202 root: null,
203 quiet: 0
206 var testVersions = [
207 "1.0.4 (beta)",
208 "2.0.1 (beta)"
211 function start() {
213 function log(msg) {
214 if (window.console && window.console.log) {
215 window.console.log(msg);
219 function createStylesheet() {
220 var style = document.createElement("style");
221 style.appendChild(document.createTextNode(""));
222 document.head.appendChild(style);
223 return style.sheet;
226 function create3DContext(canvas, attrs, version) {
227 if (!canvas) {
228 canvas = document.createElement("canvas");
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;
238 for (var i = 0; i < names.length; ++i) {
239 try {
240 context = canvas.getContext(names[i], attrs);
241 } catch (e) {
243 if (context) {
244 break;
247 return context;
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;
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;
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_();
283 else {
284 that.folder.disableUp_();
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);
296 if (reporter.noSelectedWebGLVersion) {
297 button.disabled = true;
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,
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;
326 Page.prototype.checked = function() {
327 return this.check.checked;
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;
348 var result = "failed";
349 var css = "fail";
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);
359 Page.prototype.startPage = function() {
360 if (autoScroll && this.elem.scrollIntoView) {
361 this.elem.scrollIntoView(false);
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]);
373 this.totalsElem.textContent = '';
375 var shouldRun = this.check.checked && this.folder.checked();
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();
385 return this.check.checked && this.folder.checked();
388 Page.prototype.firstTestIndex = function() {
389 return this.testIndex;
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;
400 var passedMsg = ' (Passed: ' + this.totalSuccessful + '/' + this.totalTests;
401 var skippedMsg = '';
402 if (this.totalSkipped > 0) {
403 skippedMsg = ' Skipped: ' + this.totalSkipped + '/' + this.totalTests;
405 var failedMsg = '';
406 if (this.totalFailed > 0) {
407 failedMsg = ' Failed: ' + this.totalFailed + '/' + this.totalTests;
409 var timeoutMsg = '';
410 if (this.totalTimeouts > 0) {
411 timeoutMsg = ' Timeout: ' + this.totalTimeouts + '/' + this.totalTests;
413 var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg + ' in ' + this.totalTime.toFixed(1) + ' ms)';
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';
427 this.elem.classList.add(css);
428 this.totalsElem.textContent = msg;
429 this.folder.pageFinished(this, success);
432 Page.prototype.enableTest = function(re) {
433 if (this.url.match(re)) {
434 this.check.checked = true;
435 this.folder.enableUp_();
439 Page.prototype.disableTest = function(re) {
440 if (this.url.match(re)) {
441 this.check.checked = false;
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,
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;
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;
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(".*");
493 else {
494 that.disableTest(".*", true);
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();
505 if (reporter.noSelectedWebGLVersion) {
506 button.disabled = true;
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;
527 Folder.prototype.checked = function() {
528 return this.check.checked &&
529 (this.folder ? this.folder.checked() : true);
532 Folder.prototype.firstTestIndex = function() {
533 return this.items[0].firstTestIndex();
536 Folder.prototype.numChildren = function() {
537 var numChildren = 0;
538 for (var name in this.subFolders) {
539 numChildren += this.subFolders[name].numChildren();
541 return numChildren + this.pages.length;
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();
551 for (var ii = 0; ii < this.pages.length; ++ii) {
552 this.cachedTotalTime += this.pages[ii].totalTime;
555 return this.cachedTotalTime;
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();
564 for (var ii = 0; ii < this.pages.length; ++ii) {
565 this.cachedTotalSuccessful += this.pages[ii].totalSuccessful;
568 return this.cachedTotalSuccessful;
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();
577 for (var ii = 0; ii < this.pages.length; ++ii) {
578 this.cachedTotalSkipped += this.pages[ii].totalSkipped;
581 return this.cachedTotalSkipped;
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();
590 for (var ii = 0; ii < this.pages.length; ++ii) {
591 this.cachedTotalFailed += this.pages[ii].totalFailed;
594 return this.cachedTotalFailed;
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();
603 for (var ii = 0; ii < this.pages.length; ++ii) {
604 this.cachedTotalTimeouts += this.pages[ii].totalTimeouts;
607 return this.cachedTotalTimeouts;
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();
616 for (var ii = 0; ii < this.pages.length; ++ii) {
617 this.cachedTotalTests += this.pages[ii].totalTests;
620 return this.cachedTotalTests;
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});
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();
643 var failedMsg = '';
644 if (this.totalFailed() > 0) {
645 failedMsg = ' Failed: ' + this.totalFailed() + '/' + this.totalTests();
647 var timeoutMsg = '';
648 if (this.totalTimeouts() > 0) {
649 timeoutMsg = ' Timeout: ' + this.totalTimeouts() + '/' + this.totalTests();
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);
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);
665 return subFolder;
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]);
674 return folder;
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');
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;
690 if (recurse) {
691 for (var name in this.subFolders) {
692 this.subFolders[name].disableTest(re, opt_forceRecurse);
694 for (var ii = 0; ii < this.pages.length; ++ii) {
695 this.pages[ii].disableTest(re);
700 Folder.prototype.enableUp_ = function() {
701 this.check.checked = true;
702 var parent = this.folder;
703 if (parent) {
704 parent.enableUp_();
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;
716 for (var ii = 0; ii < this.pages.length && checked == false; ++ii) {
717 checked = this.pages[ii].checked();
719 this.check.checked = checked;
720 var parent = this.folder;
721 if (parent) {
722 parent.disableUp_();
726 Folder.prototype.enableTest = function(re) {
727 if (this.name.match(re)) {
728 this.enableUp_();
730 for (var name in this.subFolders) {
731 this.subFolders[name].enableTest(re);
733 for (var ii = 0; ii < this.pages.length; ++ii) {
734 this.pages[ii].enableTest(re);
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 = {};
750 // Check to see if WebGL is supported
751 var canvas = document.createElement("canvas");
752 var ctx = create3DContext(canvas, null, 1);
754 // Check to see if WebGL2 is supported
755 var canvas2 = document.createElement("canvas");
756 var ctx2 = create3DContext(canvas2, null, 2);
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;
766 // If the WebGL2 context could be created use it to get context info
767 if (ctx2) {
768 ctx = ctx2;
771 this.noWebGL = !ctx;
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();
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);
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);
798 Reporter.prototype.enableTest = function(name) {
799 this.root.enableTest(name);
802 Reporter.prototype.disableTest = function(name) {
803 this.root.disableTest(name);
806 Reporter.prototype.disableAllTests = function() {
807 this.root.disableTest(".*", true);
810 Reporter.prototype.addEventListener = function(type, func) {
811 if (!this.callbacks[type]) {
812 this.callbacks[type] = [];
814 this.callbacks[type].push(func);
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);
824 Reporter.prototype.runTest = function(url) {
825 var page = this.pagesByURL[url];
826 testHarness.runTests({start: page.firstTestIndex(), count: 1});
829 Reporter.prototype.getFolder = function(url) {
830 return this.root.getOrCreateFolder(url);
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;
841 Reporter.prototype.startPage = function(url) {
842 var page = this.pagesByURL[url];
843 return page.startPage();
846 Reporter.prototype.addResult = function(url, msg, success, skipped) {
847 var page = this.pagesByURL[url];
848 page.addResult(msg, success, skipped);
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);
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;
869 var subtestsHit = 0;
870 var subtestsSucceeded = 0;
871 var subtestsTimedOut = 0;
872 var subtestsSkipped = 0;
873 var subtestsFailed = 0;
875 var totalTime = Date.now() - this.startTime;
877 for (var url in this.pagesByURL) {
878 var page = this.pagesByURL[url];
879 totalTests += 1;
880 if (page.totalSkipped) {
881 testsSkipped += 1;
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;
893 subtestsHit += page.totalTests;
894 subtestsSucceeded += page.totalSuccessful;
895 subtestsTimedOut += page.totalTimeouts;
896 subtestsSkipped += page.totalSkipped;
897 subtestsFailed += page.totalFailed;
900 function ratio_str(x, y, name) {
901 return x + '/' + y + ' ' + name + ' (' + (x / y * 100).toFixed(2) + '%)';
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');
910 var failedMsg = '';
911 if (testsFailed > 0) {
912 failedMsg = ' Failed ' + ratio_str(testsFailed, totalTests, 'tests') + ', ' +
913 ratio_str(subtestsFailed, subtestsHit, 'subtests');
915 var timeoutMsg = '';
916 if (testsTimedOut > 0) {
917 timeoutMsg = ' Timeout ' + ratio_str(testsTimedOut, totalTests, 'tests');
919 var msg = passedMsg + skippedMsg + failedMsg + timeoutMsg;
920 this.fullResultsNode.textContent = msg;
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";
938 var result;
939 if (totalTests && testsSucceeded == totalTests) {
940 result = 'PASS';
941 } else {
942 result = 'FAIL';
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";
949 record('PASSED', testsSucceeded, subtestsSucceeded);
950 record('NOT PASSED', totalTests - testsSucceeded, subtestsHit - subtestsSucceeded);
952 record('FAILED', testsFailed, subtestsFailed);
953 record('TIMED OUT', testsTimedOut, subtestsTimedOut);
954 record('SKIPPED', testsSkipped, subtestsSkipped);
956 tx += "\n-------------------\n\n";
958 const failureLines = [];
959 const timeoutLines = [];
960 const resultLines = [];
962 for (var url in this.pagesByURL) {
963 var page = this.pagesByURL[url];
964 resultLines.push(' "' + url + '":' + JSON.stringify(page.toJSON()));
966 if (page.totalFailed) {
967 failureLines.push(' "' + url + '",');
969 if (page.totalTimeouts) {
970 timeoutLines.push(' "' + url + '",');
974 const lines = [].concat(
976 '{',
977 ' "failures": [',
979 failureLines,
981 ' ],',
982 ' "timeouts": [',
984 timeoutLines,
986 ' ],',
987 ' "results": {',
989 resultLines,
991 ' },',
992 '}',
996 tx += lines.join('\n');
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;
1004 this.postResultsToServer(tx);
1005 } else {
1006 var e = document.getElementById("error");
1007 e.innerHTML = msg;
1008 this.postResultsToServer(msg);
1012 Reporter.prototype.postTestStartToServer = function(resultText) {
1013 this.startTime = Date.now();
1014 if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
1015 return;
1018 var xhr = new XMLHttpRequest();
1019 xhr.open('POST', "/start", true);
1020 xhr.send(null);
1023 Reporter.prototype.postResultsToServer = function(resultText) {
1024 if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
1025 return;
1028 var xhr = new XMLHttpRequest();
1029 xhr.open('POST', "/finish", true);
1030 xhr.setRequestHeader("Content-Type", "text/plain");
1031 xhr.send(resultText);
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");
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;
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;
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;
1081 getURLOptions(OPTIONS);
1083 var makeVersionSelect = function(currentVersion) {
1084 var versionSelect = document.getElementById("testVersion");
1085 var foundCurrentVersion = false;
1086 var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, '');
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;
1095 if (numericVersion == numericCurrentVersion) {
1096 foundCurrentVersion = true;
1097 option.selected = true;
1100 versionSelect.appendChild(option);
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;
1110 versionSelect.appendChild(option);
1113 versionSelect.addEventListener('change', function(ev) {
1114 window.location.href = "?version=" + versionSelect.value;
1115 }, false);
1118 makeVersionSelect(OPTIONS.version);
1120 // Make iframes
1121 var iframes = [document.getElementById("test-iframe")];
1123 var testPath = "00_test_list.txt";
1124 if (OPTIONS.root) {
1125 testPath = OPTIONS.root + "/" + testPath;
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);
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]));
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]));
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();
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();
1166 var autoScrollCheckbox = document.getElementById("autoScrollCheckbox");
1167 autoScrollCheckbox.checked = autoScrollEnabled;
1168 autoScrollCheckbox.onclick = function() {
1169 autoScrollEnabled = autoScrollCheckbox.checked;
1170 autoScroll = autoScrollEnabled;
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);
1185 var quickTestModeCheckbox = document.getElementById("quickTestModeCheckbox");
1186 quickTestModeCheckbox.checked = quickTestMode;
1187 quickTestModeCheckbox.onclick = function() {
1188 quickTestMode = quickTestModeCheckbox.checked;
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");
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);
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());
1222 if (reporter.noSelectedWebGLVersion) {
1223 button.disabled = true;
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");
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");
1249 </script>
1250 </head>
1251 <body onload="start()">
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 -->
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>
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 -->
1304 </body>
1305 </html>