|
1 <!-- |
|
2 Copyright (c) 2011 Mozilla Foundation. All rights reserved. |
|
3 Use of this source code is governed by a BSD-style license that can be |
|
4 found in the LICENSE file. |
|
5 --> |
|
6 <!DOCTYPE html> |
|
7 <html> |
|
8 <head> |
|
9 <meta charset="utf-8"> |
|
10 <title>WebGL Conformance Tests</title> |
|
11 <style> |
|
12 html, body { |
|
13 border: 0; |
|
14 margin: 0; |
|
15 height: 100%; |
|
16 height: 100%; |
|
17 text-align: center; |
|
18 font-family: monospace; |
|
19 } |
|
20 table { |
|
21 width: 100%; |
|
22 height: 100%; |
|
23 } |
|
24 .timeout { } |
|
25 .success { } |
|
26 .fail { } |
|
27 .testpage { border: 1px solid black; background-color: #ccc; } |
|
28 .testpagesuccess { border: 1px solid black; background-color: #8F8; } |
|
29 .testpagefail { border: 1px solid black; background-color: #F88; } |
|
30 .testpagetimeout { border: 1px solid black; background-color: #FC8; } |
|
31 .nowebgl { font-weight: bold; color: red; } |
|
32 #error-wrap { |
|
33 float: left; |
|
34 position: relative; |
|
35 left: 50%; |
|
36 } |
|
37 #error { |
|
38 color: red; |
|
39 float: left; |
|
40 position: relative; |
|
41 left: -50%; |
|
42 text-align: left; |
|
43 } |
|
44 ul { |
|
45 list-style: none; |
|
46 padding-left: 1em; |
|
47 } |
|
48 </style> |
|
49 <script type="text/javascript" src="resources/webgl-test-harness.js"></script> |
|
50 <script> |
|
51 var CONFORMANCE_TEST_VERSION = "1.0.1"; |
|
52 |
|
53 var OPTIONS = { |
|
54 version: CONFORMANCE_TEST_VERSION |
|
55 }; |
|
56 |
|
57 function start() { |
|
58 |
|
59 function log(msg) { |
|
60 if (window.console && window.console.log) { |
|
61 window.console.log(msg); |
|
62 } |
|
63 } |
|
64 |
|
65 function create3DContext(canvas) |
|
66 { |
|
67 if (!canvas) { |
|
68 canvas = document.createElement("canvas"); |
|
69 } |
|
70 var context = null; |
|
71 var names = ["webgl", "experimental-webgl"]; |
|
72 for (var i = 0; i < names.length; ++i) { |
|
73 try { |
|
74 context = canvas.getContext(names[i]); |
|
75 } catch (e) { |
|
76 } |
|
77 if (context) { |
|
78 break; |
|
79 } |
|
80 } |
|
81 return context; |
|
82 } |
|
83 |
|
84 var reportType = WebGLTestHarnessModule.TestHarness.reportType; |
|
85 |
|
86 var Page = function(reporter, folder, testIndex, url) { |
|
87 this.reporter = reporter; |
|
88 this.folder = folder; |
|
89 this.url = url; |
|
90 this.totalTests = 0; |
|
91 this.totalSuccessful = 0; |
|
92 this.totalTimeouts = 0; |
|
93 this.testIndex = testIndex; |
|
94 |
|
95 var li = reporter.localDoc.createElement('li'); |
|
96 var div = reporter.localDoc.createElement('div'); |
|
97 var check = reporter.localDoc.createElement('input'); |
|
98 check.type = 'checkbox'; |
|
99 check.checked = true; |
|
100 div.appendChild(check); |
|
101 var button = reporter.localDoc.createElement('input'); |
|
102 button.type = 'button'; |
|
103 button.value = 'run'; |
|
104 button.onclick = function() { |
|
105 reporter.runTest(url); |
|
106 }; |
|
107 if (reporter.noWebGL) { |
|
108 button.disabled = true; |
|
109 } |
|
110 div.appendChild(button); |
|
111 var a = reporter.localDoc.createElement('a'); |
|
112 a.href = url; |
|
113 a.target = "_blank"; |
|
114 var node = reporter.localDoc.createTextNode(url); |
|
115 a.appendChild(node); |
|
116 div.appendChild(a); |
|
117 li.setAttribute('class', 'testpage'); |
|
118 li.appendChild(div); |
|
119 var ul = reporter.localDoc.createElement('ul'); |
|
120 var node = reporter.localDoc.createTextNode(''); |
|
121 li.appendChild(ul); |
|
122 div.appendChild(node); |
|
123 this.totalsElem = node; |
|
124 this.resultElem = ul; |
|
125 this.elem = li; |
|
126 this.check = check; |
|
127 }; |
|
128 |
|
129 Page.prototype.addResult = function(msg, success) { |
|
130 ++this.totalTests; |
|
131 if (success === undefined) { |
|
132 ++this.totalTimeouts; |
|
133 var result = "timeout"; |
|
134 var css = "timeout"; |
|
135 } else if (success) { |
|
136 ++this.totalSuccessful; |
|
137 var result = "success"; |
|
138 var css = "success"; |
|
139 // don't report success. |
|
140 return; |
|
141 } else { |
|
142 var result = "failed"; |
|
143 var css = "fail"; |
|
144 } |
|
145 |
|
146 var node = this.reporter.localDoc.createTextNode(result + ': ' + msg); |
|
147 var li = this.reporter.localDoc.createElement('li'); |
|
148 li.appendChild(node); |
|
149 li.setAttribute('class', css); |
|
150 this.resultElem.appendChild(li); |
|
151 }; |
|
152 |
|
153 Page.prototype.startPage = function() { |
|
154 this.totalTests = 0; |
|
155 this.totalSuccessful = 0; |
|
156 this.totalTimeouts = 0; |
|
157 // remove previous results. |
|
158 while (this.resultElem.hasChildNodes()) { |
|
159 this.resultElem.removeChild(this.resultElem.childNodes[0]); |
|
160 } |
|
161 this.totalsElem.textContent = ''; |
|
162 return this.check.checked && this.folder.checked(); |
|
163 }; |
|
164 |
|
165 Page.prototype.firstTestIndex = function() { |
|
166 return this.testIndex; |
|
167 }; |
|
168 |
|
169 Page.prototype.finishPage = function(success) { |
|
170 var msg = ' (' + this.totalSuccessful + ' of ' + |
|
171 this.totalTests + ' passed)'; |
|
172 if (success === undefined) { |
|
173 var css = 'testpagetimeout'; |
|
174 msg = '(*timeout*)'; |
|
175 ++this.totalTests; |
|
176 ++this.totalTimeouts; |
|
177 } else if (this.totalSuccessful != this.totalTests) { |
|
178 var css = 'testpagefail'; |
|
179 } else { |
|
180 var css = 'testpagesuccess'; |
|
181 } |
|
182 this.elem.setAttribute('class', css); |
|
183 this.totalsElem.textContent = msg; |
|
184 }; |
|
185 |
|
186 var Folder = function(reporter, folder, depth, opt_name) { |
|
187 this.reporter = reporter; |
|
188 this.depth = depth; |
|
189 this.name = opt_name || ""; |
|
190 this.subFolders = {}; |
|
191 this.pages = []; |
|
192 this.items = []; |
|
193 var that = this; |
|
194 |
|
195 var doc = reporter.localDoc; |
|
196 var li = doc.createElement('li'); |
|
197 var div = doc.createElement('div'); |
|
198 var check = doc.createElement('input'); |
|
199 check.type = 'checkbox'; |
|
200 check.checked = true; |
|
201 div.appendChild(check); |
|
202 var button = doc.createElement('input'); |
|
203 button.type = 'button'; |
|
204 button.value = 'run'; |
|
205 button.onclick = function() { |
|
206 that.run(); |
|
207 }; |
|
208 if (reporter.noWebGL) { |
|
209 button.disabled = true; |
|
210 } |
|
211 div.appendChild(button); |
|
212 var h = doc.createElement('span'); |
|
213 h.appendChild(doc.createTextNode(this.name)); |
|
214 div.appendChild(h); |
|
215 var ul = doc.createElement('ul'); |
|
216 li.appendChild(div); |
|
217 li.appendChild(ul); |
|
218 this.childUL = ul; |
|
219 this.elem = li; |
|
220 this.check = check; |
|
221 }; |
|
222 |
|
223 Folder.prototype.checked = function() { |
|
224 return this.check.checked && |
|
225 (this.folder ? this.folder.checked() : true); |
|
226 }; |
|
227 |
|
228 Folder.prototype.firstTestIndex = function() { |
|
229 return this.items[0].firstTestIndex(); |
|
230 }; |
|
231 |
|
232 Folder.prototype.numChildren = function() { |
|
233 var numChildren = 0; |
|
234 for (var name in this.subFolders) { |
|
235 numChildren += this.subFolders[name].numChildren(); |
|
236 } |
|
237 return numChildren + this.pages.length; |
|
238 }; |
|
239 |
|
240 Folder.prototype.run = function() { |
|
241 var firstTestIndex = this.firstTestIndex(); |
|
242 var count = this.numChildren(); |
|
243 log("run tests: " + firstTestIndex + " to " + (firstTestIndex + count - 1)) |
|
244 testHarness.runTests(firstTestIndex, count); |
|
245 }; |
|
246 |
|
247 Folder.prototype.getSubFolder = function(name) { |
|
248 var subFolder = this.subFolders[name]; |
|
249 if (subFolder === undefined) { |
|
250 subFolder = new Folder(this.reporter, this, this.depth + 1, name); |
|
251 this.subFolders[name] = subFolder; |
|
252 this.items.push(subFolder); |
|
253 this.childUL.appendChild(subFolder.elem); |
|
254 } |
|
255 return subFolder; |
|
256 }; |
|
257 |
|
258 Folder.prototype.getOrCreateFolder = function(url) { |
|
259 var parts = url.split('/'); |
|
260 var folder = this; |
|
261 for (var pp = 0; pp < parts.length - 1; ++pp) { |
|
262 folder = folder.getSubFolder(parts[pp]); |
|
263 } |
|
264 return folder; |
|
265 }; |
|
266 |
|
267 Folder.prototype.addPage = function(page) { |
|
268 this.pages.push(page); |
|
269 this.items.push(page); |
|
270 this.childUL.appendChild(page.elem); |
|
271 }; |
|
272 |
|
273 var Reporter = function() { |
|
274 this.localDoc = document; |
|
275 this.resultElem = document.getElementById("results"); |
|
276 this.fullResultsElem = document.getElementById("fullresults"); |
|
277 var node = this.localDoc.createTextNode(''); |
|
278 this.fullResultsElem.appendChild(node); |
|
279 this.fullResultsNode = node; |
|
280 this.iframe = document.getElementById("testframe"); |
|
281 this.currentPageElem = null; |
|
282 this.totalPages = 0; |
|
283 this.pagesByURL = {}; |
|
284 var canvas = document.getElementById("webglcheck"); |
|
285 var ctx = create3DContext(canvas); |
|
286 this.noWebGL = !ctx; |
|
287 this.contextInfo = {}; |
|
288 this.root = new Folder(this, null, 0, "all"); |
|
289 this.resultElem.appendChild(this.root.elem); |
|
290 |
|
291 if (ctx) { |
|
292 this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR); |
|
293 this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION); |
|
294 this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER); |
|
295 this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS); |
|
296 this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS); |
|
297 this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS); |
|
298 this.contextInfo["ALPHA_BITS"] = ctx.getParameter(ctx.ALPHA_BITS); |
|
299 this.contextInfo["DEPTH_BITS"] = ctx.getParameter(ctx.DEPTH_BITS); |
|
300 this.contextInfo["STENCIL_BITS"] = ctx.getParameter(ctx.STENCIL_BITS); |
|
301 |
|
302 var ext = ctx.getExtension("WEBGL_debug_renderer_info"); |
|
303 if (ext) { |
|
304 this.contextInfo["UNMASKED_VENDOR"] = ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL); |
|
305 this.contextInfo["UNMASKED_RENDERER"] = ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL); |
|
306 } |
|
307 } |
|
308 }; |
|
309 |
|
310 Reporter.prototype.runTest = function(url) { |
|
311 var page = this.pagesByURL[url]; |
|
312 page.startPage(); |
|
313 this.currentPage = page; |
|
314 this.iframe.src = url; |
|
315 }; |
|
316 |
|
317 Reporter.prototype.getFolder = function(url) { |
|
318 return this.root.getOrCreateFolder(url); |
|
319 }; |
|
320 |
|
321 Reporter.prototype.addPage = function(url) { |
|
322 var folder = this.getFolder(url); |
|
323 var page = new Page(this, folder, this.totalPages, url); |
|
324 folder.addPage(page); |
|
325 ++this.totalPages; |
|
326 this.pagesByURL[url] = page; |
|
327 }; |
|
328 |
|
329 Reporter.prototype.startPage = function(url) { |
|
330 var page = this.pagesByURL[url]; |
|
331 this.currentPage = page; |
|
332 return page.startPage(); |
|
333 }; |
|
334 |
|
335 Reporter.prototype.addResult = function(msg, success) { |
|
336 if (this.currentPage != null) { |
|
337 this.currentPage.addResult(msg, success); |
|
338 } |
|
339 }; |
|
340 |
|
341 Reporter.prototype.finishPage = function(success) { |
|
342 if (this.currentPage != null) { |
|
343 this.currentPage.finishPage(success); |
|
344 this.currentPage = null; |
|
345 } |
|
346 }; |
|
347 |
|
348 Reporter.prototype.displayFinalResults = function(msg, success) { |
|
349 if (success) { |
|
350 var totalTests = 0; |
|
351 var totalSuccessful = 0; |
|
352 var totalTimeouts = 0; |
|
353 for (var url in this.pagesByURL) { |
|
354 var page = this.pagesByURL[url]; |
|
355 totalTests += page.totalTests; |
|
356 totalSuccessful += page.totalSuccessful; |
|
357 totalTimeouts += page.totalTimeouts; |
|
358 } |
|
359 var timeout = ''; |
|
360 if (totalTimeouts > 0) { |
|
361 timeout = ', ' + totalTimeouts + ' timed out'; |
|
362 } |
|
363 var msg = ' (' + totalSuccessful + ' of ' + |
|
364 totalTests + ' passed' + timeout + ')'; |
|
365 this.fullResultsNode.textContent = msg; |
|
366 |
|
367 // generate a text summary |
|
368 var tx = ""; |
|
369 tx += "WebGL Conformance Test Results\n"; |
|
370 tx += "Version " + OPTIONS.version + "\n"; |
|
371 tx += "\n"; |
|
372 tx += "-------------------\n\n"; |
|
373 tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n"; |
|
374 tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n"; |
|
375 tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n"; |
|
376 tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n"; |
|
377 tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n"; |
|
378 tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n"; |
|
379 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"; |
|
380 tx += "\n"; |
|
381 tx += "-------------------\n\n"; |
|
382 tx += "Test Summary (" + totalTests + " total tests):\n"; |
|
383 tx += "Tests PASSED: " + totalSuccessful + "\n"; |
|
384 tx += "Tests FAILED: " + (totalTests - totalSuccessful) + "\n"; |
|
385 tx += "Tests TIMED OUT: " + totalTimeouts + "\n"; |
|
386 tx += "\n"; |
|
387 tx += "-------------------\n\n"; |
|
388 if (totalSuccessful < totalTests) { |
|
389 tx += "Failures:\n\n"; |
|
390 for (var url in this.pagesByURL) { |
|
391 var page = this.pagesByURL[url]; |
|
392 var pageTotalFail = page.totalTests - page.totalSuccessful; |
|
393 if (!(page.totalTests == 0 && page.totalTimeouts == 0) && |
|
394 pageTotalFail > 0) |
|
395 { |
|
396 tx += url + ": " + pageTotalFail + " tests failed"; |
|
397 if (page.totalTimeouts) |
|
398 tx += " (" + page.totalTimeouts + " timed out)"; |
|
399 tx += "\n"; |
|
400 } |
|
401 } |
|
402 } else { |
|
403 tx += "All tests PASSED\n\n"; |
|
404 } |
|
405 tx += "\n"; |
|
406 tx += "-------------------\n\n"; |
|
407 tx += "Complete Test Results (total / pass / fail / timeout):\n\n"; |
|
408 for (var url in this.pagesByURL) { |
|
409 var page = this.pagesByURL[url]; |
|
410 var pageTotalFail = page.totalTests - page.totalSuccessful; |
|
411 if (!(page.totalTests == 0 && page.totalTimeouts == 0)) { |
|
412 tx += url + ": " + page.totalTests + " / " + |
|
413 page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + "\n"; |
|
414 } |
|
415 } |
|
416 tx += "\n"; |
|
417 tx += "-------------------\n\n"; |
|
418 tx += "Generated on: " + (new Date()).toString() + "\n"; |
|
419 |
|
420 var r = document.getElementById("testResultsAsText"); |
|
421 while (r.firstChild) r.removeChild(r.firstChild); |
|
422 r.appendChild(document.createTextNode(tx)); |
|
423 document.getElementById("showTextSummary").style.visibility = "visible"; |
|
424 } else { |
|
425 var e = document.getElementById("error"); |
|
426 e.innerHTML = msg; |
|
427 } |
|
428 }; |
|
429 |
|
430 Reporter.prototype.ready = function() { |
|
431 var loading = document.getElementById("loading"); |
|
432 loading.style.display = "none"; |
|
433 if (!this.noWebGL) { |
|
434 var button = document.getElementById("runTestsButton"); |
|
435 button.disabled = false; |
|
436 } |
|
437 }; |
|
438 |
|
439 Reporter.prototype.reportFunc = function(type, msg, success) { |
|
440 switch (type) { |
|
441 case reportType.ADD_PAGE: |
|
442 return this.addPage(msg); |
|
443 case reportType.READY: |
|
444 return this.ready(); |
|
445 case reportType.START_PAGE: |
|
446 return this.startPage(msg); |
|
447 case reportType.TEST_RESULT: |
|
448 return this.addResult(msg, success); |
|
449 case reportType.FINISH_PAGE: |
|
450 return this.finishPage(success); |
|
451 case reportType.FINISHED_ALL_TESTS: |
|
452 return this.displayFinalResults(msg, success); |
|
453 default: |
|
454 throw 'unhandled'; |
|
455 break; |
|
456 }; |
|
457 }; |
|
458 |
|
459 var getURLOptions = function(obj) { |
|
460 var s = window.location.href; |
|
461 var q = s.indexOf("?"); |
|
462 var e = s.indexOf("#"); |
|
463 if (e < 0) { |
|
464 e = s.length; |
|
465 } |
|
466 var query = s.substring(q + 1, e); |
|
467 var pairs = query.split("&"); |
|
468 for (var ii = 0; ii < pairs.length; ++ii) { |
|
469 var keyValue = pairs[ii].split("="); |
|
470 var key = keyValue[0]; |
|
471 var value = decodeURIComponent(keyValue[1]); |
|
472 obj[key] = value; |
|
473 } |
|
474 }; |
|
475 |
|
476 getURLOptions(OPTIONS); |
|
477 |
|
478 document.getElementById("testVersion").innerHTML = OPTIONS.version; |
|
479 |
|
480 var reporter = new Reporter(); |
|
481 var iframe = document.getElementById("testframe"); |
|
482 var testHarness = new WebGLTestHarnessModule.TestHarness( |
|
483 iframe, |
|
484 '00_test_list.txt', |
|
485 function(type, msg, success) { |
|
486 return reporter.reportFunc(type, msg, success); |
|
487 }, |
|
488 OPTIONS); |
|
489 window.webglTestHarness = testHarness; |
|
490 var button = document.getElementById("runTestsButton"); |
|
491 button.disabled = true; |
|
492 button.onclick = function() { |
|
493 testHarness.runTests(); |
|
494 }; |
|
495 var textbutton = document.getElementById("showTextSummary"); |
|
496 textbutton.onclick = function() { |
|
497 log("click"); |
|
498 var htmldiv = document.getElementById("testResultsHTML"); |
|
499 var textdiv = document.getElementById("testResultsText"); |
|
500 if (textdiv.style.display == "none") { |
|
501 textdiv.style.display = "block"; |
|
502 htmldiv.style.display = "none"; |
|
503 textbutton.setAttribute("value", "display html summary"); |
|
504 } else { |
|
505 textdiv.style.display = "none"; |
|
506 htmldiv.style.display = "block"; |
|
507 textbutton.setAttribute("value", "display text summary"); |
|
508 } |
|
509 }; |
|
510 if (reporter.noWebGL) { |
|
511 button.disabled = true; |
|
512 var elem = document.getElementById("nowebgl"); |
|
513 elem.style.display = ""; |
|
514 } |
|
515 } |
|
516 </script> |
|
517 </head> |
|
518 <body onload="start()"> |
|
519 <table border="2"> |
|
520 <tr style="height: 300px;"> |
|
521 <td> |
|
522 <table> |
|
523 <tr><td><img src="resources/webgl-logo.png" /><br />WebGL Conformance Test Runner<br/>Version <span id="testVersion"></span><br/><input type="button" value="run tests" id="runTestsButton"/><br/><input type="button" style="visibility: hidden;" value="display text summary" id="showTextSummary"/> |
|
524 <div id="nowebgl" class="nowebgl" style="display: none;">This browser does not appear to support WebGL</div></td></tr> |
|
525 <tr><td><div id="loading">Loading Tests...</div> |
|
526 <div style="border: 1px">Results: <span id="fullresults"></span></div> |
|
527 <canvas id="webglcheck" style="display: none;"></canvas></td></tr> |
|
528 <tr><td><div id="error-wrap"><pre id="error"></pre></div></td></tr> |
|
529 </table> |
|
530 </td> |
|
531 <td> |
|
532 <iframe id="testframe" scrolling="yes" width="100%" height="100%"></iframe> |
|
533 </td> |
|
534 </tr> |
|
535 <tr> |
|
536 <td colspan="2"> |
|
537 <div style="text-align: left; width: 100%; height: 100%; overflow: auto;"> |
|
538 <div id="testResultsHTML"><ul id="results"></ul></div> |
|
539 <div style="display: none;" id="testResultsText"><pre id="testResultsAsText"></pre></div> |
|
540 </div> |
|
541 </td> |
|
542 </tr> |
|
543 </table> |
|
544 </body> |
|
545 </html> |