| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // This is a test harness for running javascript tests in the browser. | |
| 6 // The only identifier exposed by this harness is WebGLTestHarnessModule. | |
| 7 // | |
| 8 // To use it make an HTML page with an iframe. Then call the harness like this | |
| 9 // | |
| 10 // function reportResults(type, msg, success) { | |
| 11 // ... | |
| 12 // return true; | |
| 13 // } | |
| 14 // | |
| 15 // var fileListURL = '00_test_list.txt'; | |
| 16 // var testHarness = new WebGLTestHarnessModule.TestHarness( | |
| 17 // iframe, | |
| 18 // fileListURL, | |
| 19 // reportResults); | |
| 20 // | |
| 21 // The harness will load the fileListURL and parse it for the URLs, one URL | |
| 22 // per line. URLs should be on the same domain and at the same folder level | |
| 23 // or below the main html file. If any URL ends in .txt it will be parsed | |
| 24 // as well so you can nest .txt files. URLs inside a .txt file should be | |
| 25 // relative to that text file. | |
| 26 // | |
| 27 // During startup, for each page found the reportFunction will be called with | |
| 28 // WebGLTestHarnessModule.TestHarness.reportType.ADD_PAGE and msg will be | |
| 29 // the URL of the test. | |
| 30 // | |
| 31 // Each test is required to call testHarness.reportResults. This is most easily | |
| 32 // accomplished by storing that value on the main window with | |
| 33 // | |
| 34 // window.webglTestHarness = testHarness | |
| 35 // | |
| 36 // and then adding these to functions to your tests. | |
| 37 // | |
| 38 // function reportTestResultsToHarness(success, msg) { | |
| 39 // if (window.parent.webglTestHarness) { | |
| 40 // window.parent.webglTestHarness.reportResults(success, msg); | |
| 41 // } | |
| 42 // } | |
| 43 // | |
| 44 // function notifyFinishedToHarness() { | |
| 45 // if (window.parent.webglTestHarness) { | |
| 46 // window.parent.webglTestHarness.notifyFinished(); | |
| 47 // } | |
| 48 // } | |
| 49 // | |
| 50 // This way your tests will still run without the harness and you can use | |
| 51 // any testing framework you want. | |
| 52 // | |
| 53 // Each test should call reportTestResultsToHarness with true for success if it | |
| 54 // succeeded and false if it fail followed and any message it wants to | |
| 55 // associate with the test. If your testing framework supports checking for | |
| 56 // timeout you can call it with success equal to undefined in that case. | |
| 57 // | |
| 58 // To run the tests, call testHarness.runTests(); | |
| 59 // | |
| 60 // For each test run, before the page is loaded the reportFunction will be | |
| 61 // called with WebGLTestHarnessModule.TestHarness.reportType.START_PAGE and msg | |
| 62 // will be the URL of the test. You may return false if you want the test to be | |
| 63 // skipped. | |
| 64 // | |
| 65 // For each test completed the reportFunction will be called with | |
| 66 // with WebGLTestHarnessModule.TestHarness.reportType.TEST_RESULT, | |
| 67 // success = true on success, false on failure, undefined on timeout | |
| 68 // and msg is any message the test choose to pass on. | |
| 69 // | |
| 70 // When all the tests on the page have finished your page must call | |
| 71 // notifyFinishedToHarness. If notifyFinishedToHarness is not called | |
| 72 // the harness will assume the test timed out. | |
| 73 // | |
| 74 // When all the tests on a page have finished OR the page as timed out the | |
| 75 // reportFunction will be called with | |
| 76 // WebGLTestHarnessModule.TestHarness.reportType.FINISH_PAGE | |
| 77 // where success = true if the page has completed or undefined if the page timed | |
| 78 // out. | |
| 79 // | |
| 80 // Finally, when all the tests have completed the reportFunction will be called | |
| 81 // with WebGLTestHarnessModule.TestHarness.reportType.FINISHED_ALL_TESTS. | |
| 82 // | |
| 83 | |
| 84 WebGLTestHarnessModule = function() { | |
| 85 | |
| 86 /** | |
| 87 * Wrapped logging function. | |
| 88 */ | |
| 89 var log = function(msg) { | |
| 90 if (window.console && window.console.log) { | |
| 91 window.console.log(msg); | |
| 92 } | |
| 93 }; | |
| 94 | |
| 95 /** | |
| 96 * Loads text from an external file. This function is synchronous. | |
| 97 * @param {string} url The url of the external file. | |
| 98 * @return {string} the loaded text if the request is synchronous. | |
| 99 */ | |
| 100 var loadTextFileSynchronous = function(url) { | |
| 101 var error = 'loadTextFileSynchronous failed to load url "' + url + '"'; | |
| 102 var request; | |
| 103 if (window.XMLHttpRequest) { | |
| 104 request = new XMLHttpRequest(); | |
| 105 if (request.overrideMimeType) { | |
| 106 request.overrideMimeType('text/plain'); | |
| 107 } | |
| 108 } else { | |
| 109 throw 'XMLHttpRequest is disabled'; | |
| 110 } | |
| 111 request.open('GET', url, false); | |
| 112 request.send(null); | |
| 113 if (request.readyState != 4) { | |
| 114 throw error; | |
| 115 } | |
| 116 return request.responseText; | |
| 117 }; | |
| 118 | |
| 119 var getFileList = function(url) { | |
| 120 var files = []; | |
| 121 if (url.substr(url.length - 4) == '.txt') { | |
| 122 var lines = loadTextFileSynchronous(url).split('\n'); | |
| 123 var prefix = ''; | |
| 124 var lastSlash = url.lastIndexOf('/'); | |
| 125 if (lastSlash >= 0) { | |
| 126 prefix = url.substr(0, lastSlash + 1); | |
| 127 } | |
| 128 for (var ii = 0; ii < lines.length; ++ii) { | |
| 129 var str = lines[ii].replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | |
| 130 if (str.length > 4 && | |
| 131 str[0] != '#' && | |
| 132 str[0] != ";" && | |
| 133 str.substr(0, 2) != "//") { | |
| 134 new_url = prefix + str; | |
| 135 files = files.concat(getFileList(new_url)); | |
| 136 } | |
| 137 } | |
| 138 } else { | |
| 139 files.push(url); | |
| 140 } | |
| 141 return files; | |
| 142 } | |
| 143 | |
| 144 var TestFile = function(url) { | |
| 145 this.url = url; | |
| 146 }; | |
| 147 | |
| 148 var TestHarness = function(iframe, filelistUrl, reportFunc) { | |
| 149 this.window = window; | |
| 150 this.iframe = iframe; | |
| 151 this.reportFunc = reportFunc; | |
| 152 var files = getFileList(filelistUrl); | |
| 153 this.files = []; | |
| 154 for (var ii = 0; ii < files.length; ++ii) { | |
| 155 this.files.push(new TestFile(files[ii])); | |
| 156 this.reportFunc(TestHarness.reportType.ADD_PAGE, files[ii], undefined); | |
| 157 } | |
| 158 this.nextFileIndex = files.length; | |
| 159 this.timeoutDelay = 20000; | |
| 160 }; | |
| 161 | |
| 162 TestHarness.reportType = { | |
| 163 ADD_PAGE: 1, | |
| 164 START_PAGE: 2, | |
| 165 TEST_RESULT: 3, | |
| 166 FINISH_PAGE: 4, | |
| 167 FINISHED_ALL_TESTS: 5 | |
| 168 }; | |
| 169 | |
| 170 TestHarness.prototype.runTests = function(files) { | |
| 171 this.nextFileIndex = 0; | |
| 172 this.startNextFile(); | |
| 173 }; | |
| 174 | |
| 175 TestHarness.prototype.setTimeout = function() { | |
| 176 var that = this; | |
| 177 this.timeoutId = this.window.setTimeout(function() { | |
| 178 that.timeout(); | |
| 179 }, this.timeoutDelay); | |
| 180 }; | |
| 181 | |
| 182 TestHarness.prototype.clearTimeout = function() { | |
| 183 this.window.clearTimeout(this.timeoutId); | |
| 184 }; | |
| 185 | |
| 186 TestHarness.prototype.startNextFile = function() { | |
| 187 if (this.nextFileIndex >= this.files.length) { | |
| 188 log("done"); | |
| 189 this.reportFunc(TestHarness.reportType.FINISHED_ALL_TESTS, | |
| 190 '', undefined); | |
| 191 } else { | |
| 192 this.currentFile = this.files[this.nextFileIndex++]; | |
| 193 log("loading: " + this.currentFile.url); | |
| 194 if (this.reportFunc(TestHarness.reportType.START_PAGE, | |
| 195 this.currentFile.url, undefined)) { | |
| 196 this.iframe.src = this.currentFile.url; | |
| 197 this.setTimeout(); | |
| 198 } else { | |
| 199 this.reportResults(false, "skipped"); | |
| 200 this.notifyFinished(); | |
| 201 } | |
| 202 } | |
| 203 }; | |
| 204 | |
| 205 TestHarness.prototype.reportResults = function (success, msg) { | |
| 206 this.clearTimeout(); | |
| 207 log(success ? "PASS" : "FAIL", msg); | |
| 208 this.reportFunc(TestHarness.reportType.TEST_RESULT, msg, success); | |
| 209 // For each result we get, reset the timeout | |
| 210 this.setTimeout(); | |
| 211 }; | |
| 212 | |
| 213 TestHarness.prototype.notifyFinished = function () { | |
| 214 this.clearTimeout(); | |
| 215 var url = this.currentFile ? this.currentFile.url : 'unknown'; | |
| 216 log(url + ": finished"); | |
| 217 this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, true); | |
| 218 this.startNextFile(); | |
| 219 }; | |
| 220 | |
| 221 TestHarness.prototype.timeout = function() { | |
| 222 this.clearTimeout(); | |
| 223 var url = this.currentFile ? this.currentFile.url : 'unknown'; | |
| 224 log(url + ": timeout"); | |
| 225 this.reportFunc(TestHarness.reportType.FINISH_PAGE, url, undefined); | |
| 226 this.startNextFile(); | |
| 227 }; | |
| 228 | |
| 229 TestHarness.prototype.setTimeoutDelay = function(x) { | |
| 230 this.timeoutDelay = x; | |
| 231 }; | |
| 232 | |
| 233 return { | |
| 234 'TestHarness': TestHarness | |
| 235 }; | |
| 236 | |
| 237 }(); | |
| 238 | |
| 239 | |
| 240 | |
| OLD | NEW |