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.
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>
17 box-sizing: border-box;
26 font-family: Verdana, Arial, sans-serif;
30 input[type=button], select {
31 padding:
2px
6px
2px
6px;
33 border:
1px solid #
888;
40 text-decoration: none;
44 border-bottom:
1px solid #
66D;
55 right: calc(
10% +
50px);
61 @media screen and (max-width:
500px) {
74 border-bottom:
1px solid #CCC;
91 height: calc(
100% -
170px);
93 left: calc(
90% -
50px);
94 transition: left
0.15s;
96 #iframe-container.iframe-shown {
100 display: inline-block;
101 vertical-align: middle;
105 -webkit-appearance: none;
108 display: inline-block;
109 vertical-align: middle;
111 width: calc(
100% -
20px);
113 border:
1px solid black;
117 margin-bottom:
1.5em;
127 /* to hide checkboxes from parent headers */
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;
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; }
187 <script type=
"application/javascript" src=
"js/webgl-test-harness.js"></script>
191 window
.onbeforeunload = function() {
192 // Prompt user before reloading
196 var DEFAULT_CONFORMANCE_TEST_VERSION
= "2.0.1 (beta)";
199 version
: DEFAULT_CONFORMANCE_TEST_VERSION
,
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
);
226 function create3DContext(canvas
, attrs
, version
) {
228 canvas
= document
.createElement("canvas");
234 names
= ["webgl2"]; break;
236 names
= ["webgl", "experimental-webgl"]; break;
238 for (var i
= 0; i
< names
.length
; ++i
) {
240 context
= canvas
.getContext(names
[i
], attrs
);
250 var reportType
= WebGLTestHarnessModule
.TestHarness
.reportType
;
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
;
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();
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() {
281 that
.folder
.enableUp_();
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() {
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,
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
);
314 li
.setAttribute('class', 'testpage');
316 var ul
= reporter
.localDoc
.createElement('ul');
317 var node
= reporter
.localDoc
.createTextNode('');
319 div
.appendChild(node
);
320 this.totalsElem
= node
;
321 this.resultElem
= ul
;
326 Page
.prototype.checked = function() {
327 return this.check
.checked
;
330 Page
.prototype.addResult = function(msg
, success
, skipped
) {
332 if (success
=== undefined) {
333 ++this.totalTimeouts
;
334 var result
= "timeout";
336 } else if (success
) {
337 ++this.totalSuccessful
;
338 // don't report success.
343 // Skipped tests are counted as both skips and failures (because we
344 // don't want to accidentally accept a conformance submission with
348 var result
= "failed";
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);
364 this.totalSuccessful
= 0;
365 this.totalSkipped
= 0;
366 this.totalFailed
= 0;
367 this.totalTimeouts
= 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();
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();
395 this.totalTime
= Date
.now() - this.startTime
;
400 var passedMsg
= ' (Passed: ' + this.totalSuccessful
+ '/' + this.totalTests
;
402 if (this.totalSkipped
> 0) {
403 skippedMsg
= ' Skipped: ' + this.totalSkipped
+ '/' + this.totalTests
;
406 if (this.totalFailed
> 0) {
407 failedMsg
= ' Failed: ' + this.totalFailed
+ '/' + this.totalTests
;
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';
419 ++this.totalTimeouts
;
420 } else if (this.totalSkipped
) {
421 var css
= 'testpageskipped';
422 } else if (this.totalSuccessful
!= this.totalTests
) {
423 var css
= 'testpagefail';
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() {
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
;
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
= {};
468 this.folder
= folder
;
469 this.cachedTotalTime
= 0;
470 this.cachedTotalSuccessful
= 0;
471 this.cachedTotalSkipped
= 0;
472 this.cachedTotalTimeouts
= 0;
473 this.cachedTotalTests
= 0;
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() {
491 that
.enableTest(".*");
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
;
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
);
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() {
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();
640 if (this.totalSkipped() > 0) {
641 skippedMsg
= ' Skipped: ' + this.totalSkipped() + '/' + this.totalTests();
644 if (this.totalFailed() > 0) {
645 failedMsg
= ' Failed: ' + this.totalFailed() + '/' + this.totalTests();
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)';
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
);
668 Folder
.prototype.getOrCreateFolder = function(url
) {
669 var parts
= url
.split('/');
671 for (var pp
= 0; pp
< parts
.length
- 1; ++pp
) {
672 folder
= folder
.getSubFolder(parts
[pp
]);
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
) {
686 if (this.name
.match(re
)) {
687 this.check
.checked
= false;
688 recurse
= opt_forceRecurse
;
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
;
708 Folder
.prototype.disableUp_ = function() {
710 for (var name
in this.subFolders
) {
711 checked
= this.subFolders
[name
].checked();
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
;
726 Folder
.prototype.enableTest = function(re
) {
727 if (this.name
.match(re
)) {
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;
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
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();
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");
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
);
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);
861 Reporter
.prototype.displayFinalResults = function(msg
, success
) {
864 var testsSucceeded
= 0;
866 var testsSkipped
= 0;
867 var testsTimedOut
= 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
];
880 if (page
.totalSkipped
) {
883 if (page
.totalFailed
) {
885 } else if (page
.totalTimeouts
) {
887 } else if (page
.totalSuccessful
) {
888 if (page
.totalSuccessful
!= page
.totalTests
)
889 throw successes_not_equal_total
;
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');
907 if (testsSkipped
> 0) {
908 skippedMsg
= ' Skipped ' + ratio_str(testsSkipped
, totalTests
, 'tests');
911 if (testsFailed
> 0) {
912 failedMsg
= ' Failed ' + ratio_str(testsFailed
, totalTests
, 'tests') + ', ' +
913 ratio_str(subtestsFailed
, subtestsHit
, 'subtests');
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
924 tx
+= "WebGL Conformance Test Results\n";
925 tx
+= "Version " + OPTIONS
.version
+ "\n";
926 tx
+= "Generated on: " + (new Date()).toString() + "\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";
939 if (totalTests
&& testsSucceeded
== totalTests
) {
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(
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
);
1006 var e
= document
.getElementById("error");
1008 this.postResultsToServer(msg
);
1012 Reporter
.prototype.postTestStartToServer = function(resultText
) {
1013 this.startTime
= Date
.now();
1014 if(OPTIONS
.postResults
== undefined || OPTIONS
.postResults
== 0) {
1018 var xhr
= new XMLHttpRequest();
1019 xhr
.open('POST', "/start", true);
1023 Reporter
.prototype.postResultsToServer = function(resultText
) {
1024 if(OPTIONS
.postResults
== undefined || OPTIONS
.postResults
== 0) {
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
) {
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
);
1064 var getURLOptions = function(obj
) {
1065 var s
= window
.location
.href
;
1066 var q
= s
.indexOf("?");
1067 var e
= s
.indexOf("#");
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]);
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
;
1118 makeVersionSelect(OPTIONS
.version
);
1121 var iframes
= [document
.getElementById("test-iframe")];
1123 var testPath
= "00_test_list.txt";
1125 testPath
= OPTIONS
.root
+ "/" + testPath
;
1128 var reporter
= new Reporter(iframes
);
1129 var testHarness
= new WebGLTestHarnessModule
.TestHarness(
1132 function(type
, url
, msg
, success
, skipped
) {
1133 return reporter
.reportFunc(type
, url
, msg
, success
, skipped
);
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.
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);
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() {
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");
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
);
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
;
1241 iframeContainer
.classList
.add("iframe-shown");
1242 iframeToggle
.value
= iframeToggle
.getAttribute("data-value-shown");
1244 iframeContainer
.classList
.remove("iframe-shown");
1245 iframeToggle
.value
= iframeToggle
.getAttribute("data-value-hidden");
1251 <body onload=
"start()">
1254 <div id=
"testResultsHTML">
1258 <div style=
"display: none;" id=
"testResultsText">
1259 <pre id=
"testResultsAsText"></pre>
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>
1270 <div style=
"text-align:center">
1271 <img src=
"resources/webgl-logo.png" alt=
"WebGL" id=
"logo"/>
1273 Conformance Test Runner
1276 <select id=
"testVersion">
1278 <a href=
"../../conformance-suites/">(older versions?)
</a>
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>
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
1290 <div id=
"noselectedwebgl" class=
"nowebgl" style=
"display: none;">
1291 This browser does not appear to support the selected version of WebGL
1296 <div id=
"fullresults">
1299 <div id=
"error-wrap">
1300 <pre id=
"error"></pre>
1302 </div> <!-- end of header -->