Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(841)

Side by Side Diff: third_party/webgl/sdk/tests/resources/webgl-test-harness.js

Issue 10399113: Roll webgl conformance tests to r17874: part 2, adding r17874 (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 ** Copyright (c) 2012 The Khronos Group Inc.
3 **
4 ** Permission is hereby granted, free of charge, to any person obtaining a
5 ** copy of this software and/or associated documentation files (the
6 ** "Materials"), to deal in the Materials without restriction, including
7 ** without limitation the rights to use, copy, modify, merge, publish,
8 ** distribute, sublicense, and/or sell copies of the Materials, and to
9 ** permit persons to whom the Materials are furnished to do so, subject to
10 ** the following conditions:
11 **
12 ** The above copyright notice and this permission notice shall be included
13 ** in all copies or substantial portions of the Materials.
14 **
15 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
22 */
23
24 // This is a test harness for running javascript tests in the browser.
25 // The only identifier exposed by this harness is WebGLTestHarnessModule.
26 //
27 // To use it make an HTML page with an iframe. Then call the harness like this
28 //
29 // function reportResults(type, msg, success) {
30 // ...
31 // return true;
32 // }
33 //
34 // var fileListURL = '00_test_list.txt';
35 // var testHarness = new WebGLTestHarnessModule.TestHarness(
36 // iframe,
37 // fileListURL,
38 // reportResults,
39 // options);
40 //
41 // The harness will load the fileListURL and parse it for the URLs, one URL
42 // per line preceded by options, see below. URLs should be on the same domain
43 // and at the same folder level or below the main html file. If any URL ends
44 // in .txt it will be parsed as well so you can nest .txt files. URLs inside a
45 // .txt file should be relative to that text file.
46 //
47 // During startup, for each page found the reportFunction will be called with
48 // WebGLTestHarnessModule.TestHarness.reportType.ADD_PAGE and msg will be
49 // the URL of the test.
50 //
51 // Each test is required to call testHarness.reportResults. This is most easily
52 // accomplished by storing that value on the main window with
53 //
54 // window.webglTestHarness = testHarness
55 //
56 // and then adding these to functions to your tests.
57 //
58 // function reportTestResultsToHarness(success, msg) {
59 // if (window.parent.webglTestHarness) {
60 // window.parent.webglTestHarness.reportResults(success, msg);
61 // }
62 // }
63 //
64 // function notifyFinishedToHarness() {
65 // if (window.parent.webglTestHarness) {
66 // window.parent.webglTestHarness.notifyFinished();
67 // }
68 // }
69 //
70 // This way your tests will still run without the harness and you can use
71 // any testing framework you want.
72 //
73 // Each test should call reportTestResultsToHarness with true for success if it
74 // succeeded and false if it fail followed and any message it wants to
75 // associate with the test. If your testing framework supports checking for
76 // timeout you can call it with success equal to undefined in that case.
77 //
78 // To run the tests, call testHarness.runTests();
79 //
80 // For each test run, before the page is loaded the reportFunction will be
81 // called with WebGLTestHarnessModule.TestHarness.reportType.START_PAGE and msg
82 // will be the URL of the test. You may return false if you want the test to be
83 // skipped.
84 //
85 // For each test completed the reportFunction will be called with
86 // with WebGLTestHarnessModule.TestHarness.reportType.TEST_RESULT,
87 // success = true on success, false on failure, undefined on timeout
88 // and msg is any message the test choose to pass on.
89 //
90 // When all the tests on the page have finished your page must call
91 // notifyFinishedToHarness. If notifyFinishedToHarness is not called
92 // the harness will assume the test timed out.
93 //
94 // When all the tests on a page have finished OR the page as timed out the
95 // reportFunction will be called with
96 // WebGLTestHarnessModule.TestHarness.reportType.FINISH_PAGE
97 // where success = true if the page has completed or undefined if the page timed
98 // out.
99 //
100 // Finally, when all the tests have completed the reportFunction will be called
101 // with WebGLTestHarnessModule.TestHarness.reportType.FINISHED_ALL_TESTS.
102 //
103 // Harness Options
104 //
105 // These are passed in to the TestHarness as a JavaScript object
106 //
107 // version: (required!)
108 //
109 // Specifies a version used to filter tests. Tests marked as requiring
110 // a version greater than this version will not be included.
111 //
112 // example: new TestHarness(...., {version: "3.1.2"});
113 //
114 // minVersion:
115 //
116 // Specifies the minimum version a test must require to be included.
117 // This basically flips the filter so that only tests marked with
118 // --min-version will be included if they are at this minVersion or
119 // greater.
120 //
121 // example: new TestHarness(...., {minVersion: "2.3.1"});
122 //
123 // fast:
124 //
125 // Specifies to skip any tests marked as slow.
126 //
127 // example: new TestHarness(..., {fast: true});
128 //
129 // Test Options:
130 //
131 // Any test URL or .txt file can be prefixed by the following options
132 //
133 // min-version:
134 //
135 // Sets the minimum version requires to include this test. A version is
136 // passed into the harness options. Any test marked as requiring a
137 // min-version greater than the version passed to the harness is skipped.
138 // This allows you to add new tests to a suite of tests for a future
139 // version of the suite without including the test in the current version.
140 // If no -min-version is specified it is inheriited from the .txt file
141 // including it. The default is 1.0.0
142 //
143 // example: --min-version 2.1.3 sometest.html
144 //
145 // slow:
146 //
147 // Marks a test as slow. Slow tests can be skipped by passing fastOnly: true
148 // to the TestHarness. Of course you need to pass all tests but sometimes
149 // you'd like to test quickly and run only the fast subset of tests.
150 //
151 // example: --slow some-test-that-takes-2-mins.html
152 //
153
154 WebGLTestHarnessModule = function() {
155
156 /**
157 * Wrapped logging function.
158 */
159 var log = function(msg) {
160 if (window.console && window.console.log) {
161 window.console.log(msg);
162 }
163 };
164
165 /**
166 * Loads text from an external file. This function is synchronous.
167 * @param {string} url The url of the external file.
168 * @param {!function(bool, string): void} callback that is sent a bool for
169 * success and the string.
170 */
171 var loadTextFileAsynchronous = function(url, callback) {
172 log ("loading: " + url);
173 var error = 'loadTextFileSynchronous failed to load url "' + url + '"';
174 var request;
175 if (window.XMLHttpRequest) {
176 request = new XMLHttpRequest();
177 if (request.overrideMimeType) {
178 request.overrideMimeType('text/plain');
179 }
180 } else {
181 throw 'XMLHttpRequest is disabled';
182 }
183 try {
184 request.open('GET', url, true);
185 request.onreadystatechange = function() {
186 if (request.readyState == 4) {
187 var text = '';
188 // HTTP reports success with a 200 status. The file protocol reports
189 // success with zero. HTTP does not use zero as a status code (they
190 // start at 100).
191 // https://developer.mozilla.org/En/Using_XMLHttpRequest
192 var success = request.status == 200 || request.status == 0;
193 if (success) {
194 text = request.responseText;
195 }
196 log("loaded: " + url);
197 callback(success, text);
198 }
199 };
200 request.send(null);
201 } catch (e) {
202 log("failed to load: " + url);
203 callback(false, '');
204 }
205 };
206
207 /**
208 * Compare version strings.
209 */
210 var greaterThanOrEqualToVersion = function(have, want) {
211 have = have.split(" ")[0].split(".");
212 want = want.split(" ")[0].split(".");
213
214 //have 1.2.3 want 1.1
215 //have 1.1.1 want 1.1
216 //have 1.0.9 want 1.1
217 //have 1.1 want 1.1.1
218
219 for (var ii = 0; ii < want.length; ++ii) {
220 var wantNum = parseInt(want[ii]);
221 var haveNum = have[ii] ? parseInt(have[ii]) : 0
222 if (haveNum < wantNum) {
223 return false;
224 }
225 }
226 return true;
227 };
228
229 /**
230 * Reads a file, recursively adding files referenced inside.
231 *
232 * Each line of URL is parsed, comments starting with '#' or ';'
233 * or '//' are stripped.
234 *
235 * arguments beginning with -- are extracted
236 *
237 * lines that end in .txt are recursively scanned for more files
238 * other lines are added to the list of files.
239 *
240 * @param {string} url The url of the file to read.
241 * @param {void function(boolean, !Array.<string>)} callback.
242 * Callback that is called with true for success and an
243 * array of filenames.
244 * @param {Object} options. Optional options
245 *
246 * Options:
247 * version: {string} The version of the conformance test.
248 * Tests with the argument --min-version <version> will
249 * be ignored version is less then <version>
250 *
251 */
252 var getFileList = function(url, callback, options) {
253 var files = [];
254
255 var copyObject = function(obj) {
256 return JSON.parse(JSON.stringify(obj));
257 };
258
259 var toCamelCase = function(str) {
260 return str.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase() });
261 };
262
263 var globalOptions = copyObject(options);
264 globalOptions.defaultVersion = "1.0";
265
266 var getFileListImpl = function(prefix, line, lineNum, hierarchicalOptions, cal lback) {
267 var files = [];
268
269 var args = line.split(/\s+/);
270 var nonOptions = [];
271 var useTest = true;
272 var testOptions = {};
273 for (var jj = 0; jj < args.length; ++jj) {
274 var arg = args[jj];
275 if (arg[0] == '-') {
276 if (arg[1] != '-') {
277 throw ("bad option at in " + url + ":" + lineNum + ": " + arg);
278 }
279 var option = arg.substring(2);
280 switch (option) {
281 // no argument options.
282 case 'slow':
283 testOptions[toCamelCase(option)] = true;
284 break;
285 // one argument options.
286 case 'min-version':
287 ++jj;
288 testOptions[toCamelCase(option)] = args[jj];
289 break;
290 default:
291 throw ("bad unknown option '" + option + "' at in " + url + ":" + li neNum + ": " + arg);
292 }
293 } else {
294 nonOptions.push(arg);
295 }
296 }
297 var url = prefix + nonOptions.join(" ");
298
299 if (url.substr(url.length - 4) != '.txt') {
300 var minVersion = testOptions.minVersion;
301 if (!minVersion) {
302 minVersion = hierarchicalOptions.defaultVersion;
303 }
304 var slow = testOptions.slow;
305 if (!slow) {
306 slow = hierarchicalOptions.defaultSlow;
307 }
308
309 if (globalOptions.fast && slow) {
310 useTest = false;
311 } else if (globalOptions.minVersion) {
312 useTest = greaterThanOrEqualToVersion(minVersion, globalOptions.minVersi on);
313 } else {
314 useTest = greaterThanOrEqualToVersion(globalOptions.version, minVersion) ;
315 }
316 }
317
318 if (!useTest) {
319 callback(true, []);
320 return;
321 }
322
323 if (url.substr(url.length - 4) == '.txt') {
324 // If a version was explicity specified pass it down.
325 if (testOptions.minVersion) {
326 hierarchicalOptions.defaultVersion = testOptions.minVersion;
327 }
328 if (testOptions.slow) {
329 hierarchicalOptions.defaultSlow = testOptions.slow;
330 }
331 loadTextFileAsynchronous(url, function() {
332 return function(success, text) {
333 if (!success) {
334 callback(false, '');
335 return;
336 }
337 var lines = text.split('\n');
338 var prefix = '';
339 var lastSlash = url.lastIndexOf('/');
340 if (lastSlash >= 0) {
341 prefix = url.substr(0, lastSlash + 1);
342 }
343 var fail = false;
344 var count = 1;
345 var index = 0;
346 for (var ii = 0; ii < lines.length; ++ii) {
347 var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, '');
348 if (str.length > 4 &&
349 str[0] != '#' &&
350 str[0] != ";" &&
351 str.substr(0, 2) != "//") {
352 ++count;
353 getFileListImpl(prefix, str, ii + 1, copyObject(hierarchicalOption s), function(index) {
354 return function(success, new_files) {
355 //log("got files: " + new_files.length);
356 if (success) {
357 files[index] = new_files;
358 }
359 finish(success);
360 };
361 }(index++));
362 }
363 }
364 finish(true);
365
366 function finish(success) {
367 if (!success) {
368 fail = true;
369 }
370 --count;
371 //log("count: " + count);
372 if (!count) {
373 callback(!fail, files);
374 }
375 }
376 }
377 }());
378 } else {
379 files.push(url);
380 callback(true, files);
381 }
382 };
383
384 getFileListImpl('', url, 1, globalOptions, function(success, files) {
385 // flatten
386 var flat = [];
387 flatten(files);
388 function flatten(files) {
389 for (var ii = 0; ii < files.length; ++ii) {
390 var value = files[ii];
391 if (typeof(value) == "string") {
392 flat.push(value);
393 } else {
394 flatten(value);
395 }
396 }
397 }
398 callback(success, flat);
399 });
400 };
401
402 var TestFile = function(url) {
403 this.url = url;
404 };
405
406 var TestHarness = function(iframe, filelistUrl, reportFunc, options) {
407 this.window = window;
408 this.iframe = iframe;
409 this.reportFunc = reportFunc;
410 this.timeoutDelay = 20000;
411 this.files = [];
412
413 var that = this;
414 getFileList(filelistUrl, function() {
415 return function(success, files) {
416 that.addFiles_(success, files);
417 };
418 }(), options);
419
420 };
421
422 TestHarness.reportType = {
423 ADD_PAGE: 1,
424 READY: 2,
425 START_PAGE: 3,
426 TEST_RESULT: 4,
427 FINISH_PAGE: 5,
428 FINISHED_ALL_TESTS: 6
429 };
430
431 TestHarness.prototype.addFiles_ = function(success, files) {
432 if (!success) {
433 this.reportFunc(
434 TestHarness.reportType.FINISHED_ALL_TESTS,
435 'Unable to load tests. Are you running locally?\n' +
436 'You need to run from a server or configure your\n' +
437 'browser to allow access to local files (not recommended).\n\n' +
438 'Note: An easy way to run from a server:\n\n' +
439 '\tcd path_to_tests\n' +
440 '\tpython -m SimpleHTTPServer\n\n' +
441 'then point your browser to ' +
442 '<a href="http://localhost:8000/webgl-conformance-tests.html">' +
443 'http://localhost:8000/webgl-conformance-tests.html</a>',
444 false)
445 return;
446 }
447 log("total files: " + files.length);
448 for (var ii = 0; ii < files.length; ++ii) {
449 log("" + ii + ": " + files[ii]);
450 this.files.push(new TestFile(files[ii]));
451 this.reportFunc(TestHarness.reportType.ADD_PAGE, files[ii], undefined);
452 }
453 this.reportFunc(TestHarness.reportType.READY, undefined, undefined);
454 }
455
456 TestHarness.prototype.runTests = function(opt_start, opt_count) {
457 var count = opt_count || this.files.length;
458 this.nextFileIndex = opt_start || 0;
459 this.lastFileIndex = this.nextFileIndex + count;
460 this.startNextFile();
461 };
462
463 TestHarness.prototype.setTimeout = function() {
464 var that = this;
465 this.timeoutId = this.window.setTimeout(function() {
466 that.timeout();
467 }, this.timeoutDelay);
468 };
469
470 TestHarness.prototype.clearTimeout = function() {
471 this.window.clearTimeout(this.timeoutId);
472 };
473
474 TestHarness.prototype.startNextFile = function() {
475 if (this.nextFileIndex >= this.lastFileIndex) {
476 log("done");
477 this.reportFunc(TestHarness.reportType.FINISHED_ALL_TESTS,
478 '', true);
479 } else {
480 this.currentFile = this.files[this.nextFileIndex++];
481 log("loading: " + this.currentFile.url);
482 if (this.reportFunc(TestHarness.reportType.START_PAGE,
483 this.currentFile.url, undefined)) {
484 this.iframe.src = this.currentFile.url;
485 this.setTimeout();
486 } else {
487 this.reportResults(false, "skipped");
488 this.notifyFinished();
489 }
490 }
491 };
492
493 TestHarness.prototype.reportResults = function (success, msg) {
494 this.clearTimeout();
495 log(success ? "PASS" : "FAIL", msg);
496 this.reportFunc(TestHarness.reportType.TEST_RESULT, msg, success);
497 // For each result we get, reset the timeout
498 this.setTimeout();
499 };
500
501 TestHarness.prototype.notifyFinished = function () {
502 this.clearTimeout();
503 var url = this.currentFile ? this.currentFile.url : 'unknown';
504 log(url + ": finished");
505 this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, true);
506 this.startNextFile();
507 };
508
509 TestHarness.prototype.timeout = function() {
510 this.clearTimeout();
511 var url = this.currentFile ? this.currentFile.url : 'unknown';
512 log(url + ": timeout");
513 this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, undefined);
514 this.startNextFile();
515 };
516
517 TestHarness.prototype.setTimeoutDelay = function(x) {
518 this.timeoutDelay = x;
519 };
520
521 return {
522 'TestHarness': TestHarness
523 };
524
525 }();
526
527
528
OLDNEW
« no previous file with comments | « third_party/webgl/sdk/tests/resources/webgl-logo.png ('k') | third_party/webgl/sdk/tests/webgl-conformance-tests.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698