helpers.js (7175B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 6 // The path to the top level directory. 7 const depth = "../../../../"; 8 9 var testGenerator; 10 var testHarnessGenerator; 11 var workerScriptPaths = []; 12 13 loadScript("dom/quota/test/common/mochitest.js"); 14 15 function loadScript(path) { 16 const url = new URL(depth + path, window.location.href); 17 const request = new XMLHttpRequest(); 18 request.open("GET", url, false); // `false` makes the request synchronous 19 request.send(null); 20 // eslint-disable-next-line no-eval 21 window.eval(request.responseText); // global eval 22 } 23 24 function loadWorkerScript(path) { 25 const url = new URL(depth + path, window.location.href); 26 workerScriptPaths.push(url.href); 27 } 28 29 function* testHarnessSteps() { 30 function nextTestHarnessStep(val) { 31 testHarnessGenerator.next(val); 32 } 33 34 info("Enabling storage testing"); 35 36 enableStorageTesting().then(nextTestHarnessStep); 37 yield undefined; 38 39 info("Pushing preferences"); 40 41 SpecialPowers.pushPrefEnv( 42 { 43 set: [["dom.storageManager.prompt.testing", true]], 44 }, 45 nextTestHarnessStep 46 ); 47 yield undefined; 48 49 info("Clearing old databases"); 50 51 clearAllDatabases(nextTestHarnessStep); 52 yield undefined; 53 54 info("Running test in given scopes"); 55 56 if (workerScriptPaths.length) { 57 info("Running test in a worker"); 58 59 let workerScriptBlob = new Blob(["(" + workerScript.toString() + ")();"], { 60 type: "text/javascript", 61 }); 62 let workerScriptURL = URL.createObjectURL(workerScriptBlob); 63 64 let worker = new Worker(workerScriptURL); 65 66 worker.onerror = function (event) { 67 ok(false, "Worker had an error: " + event.message); 68 worker.terminate(); 69 nextTestHarnessStep(); 70 }; 71 72 worker.onmessage = function (event) { 73 let message = event.data; 74 switch (message.op) { 75 case "ok": 76 ok(message.condition, message.name + " - " + message.diag); 77 break; 78 79 case "todo": 80 todo(message.condition, message.name, message.diag); 81 break; 82 83 case "info": 84 info(message.msg); 85 break; 86 87 case "ready": 88 worker.postMessage({ op: "load", files: workerScriptPaths }); 89 break; 90 91 case "loaded": 92 worker.postMessage({ op: "start" }); 93 break; 94 95 case "done": 96 ok(true, "Worker finished"); 97 nextTestHarnessStep(); 98 break; 99 100 case "clearAllDatabases": 101 clearAllDatabases(function () { 102 worker.postMessage({ op: "clearAllDatabasesDone" }); 103 }); 104 break; 105 106 default: 107 ok( 108 false, 109 "Received a bad message from worker: " + JSON.stringify(message) 110 ); 111 nextTestHarnessStep(); 112 } 113 }; 114 115 URL.revokeObjectURL(workerScriptURL); 116 117 yield undefined; 118 119 worker.terminate(); 120 worker = null; 121 122 clearAllDatabases(nextTestHarnessStep); 123 yield undefined; 124 } 125 126 info("Running test in main thread"); 127 128 // Now run the test script in the main thread. 129 if (testSteps.constructor.name === "AsyncFunction") { 130 SimpleTest.registerCleanupFunction(async function () { 131 await requestFinished(clearAllDatabases()); 132 }); 133 134 add_task(testSteps); 135 } else { 136 testGenerator = testSteps(); 137 testGenerator.next(); 138 139 yield undefined; 140 } 141 } 142 143 if (!window.runTest) { 144 window.runTest = function () { 145 SimpleTest.waitForExplicitFinish(); 146 testHarnessGenerator = testHarnessSteps(); 147 testHarnessGenerator.next(); 148 }; 149 } 150 151 function finishTest() { 152 SimpleTest.executeSoon(function () { 153 clearAllDatabases(function () { 154 SimpleTest.finish(); 155 }); 156 }); 157 } 158 159 function grabArgAndContinueHandler(arg) { 160 testGenerator.next(arg); 161 } 162 163 function continueToNextStep() { 164 SimpleTest.executeSoon(function () { 165 testGenerator.next(); 166 }); 167 } 168 169 function continueToNextStepSync() { 170 testGenerator.next(); 171 } 172 173 function workerScript() { 174 "use strict"; 175 176 self.testGenerator = null; 177 178 self.repr = function (_thing_) { 179 if (typeof _thing_ == "undefined") { 180 return "undefined"; 181 } 182 183 let str; 184 185 try { 186 str = _thing_ + ""; 187 } catch (e) { 188 return "[" + typeof _thing_ + "]"; 189 } 190 191 if (typeof _thing_ == "function") { 192 str = str.replace(/^\s+/, ""); 193 let idx = str.indexOf("{"); 194 if (idx != -1) { 195 str = str.substr(0, idx) + "{...}"; 196 } 197 } 198 199 return str; 200 }; 201 202 self.ok = function (_condition_, _name_, _diag_) { 203 self.postMessage({ 204 op: "ok", 205 condition: !!_condition_, 206 name: _name_, 207 diag: _diag_, 208 }); 209 }; 210 211 self.is = function (_a_, _b_, _name_) { 212 let pass = _a_ == _b_; 213 let diag = pass ? "" : "got " + repr(_a_) + ", expected " + repr(_b_); 214 ok(pass, _name_, diag); 215 }; 216 217 self.isnot = function (_a_, _b_, _name_) { 218 let pass = _a_ != _b_; 219 let diag = pass ? "" : "didn't expect " + repr(_a_) + ", but got it"; 220 ok(pass, _name_, diag); 221 }; 222 223 self.todo = function (_condition_, _name_, _diag_) { 224 self.postMessage({ 225 op: "todo", 226 condition: !!_condition_, 227 name: _name_, 228 diag: _diag_, 229 }); 230 }; 231 232 self.info = function (_msg_) { 233 self.postMessage({ op: "info", msg: _msg_ }); 234 }; 235 236 self.executeSoon = function (_fun_) { 237 var channel = new MessageChannel(); 238 channel.port1.postMessage(""); 239 channel.port2.onmessage = function (event) { 240 _fun_(); 241 }; 242 }; 243 244 self.finishTest = function () { 245 self.postMessage({ op: "done" }); 246 }; 247 248 self.grabArgAndContinueHandler = function (_arg_) { 249 testGenerator.next(_arg_); 250 }; 251 252 self.continueToNextStep = function () { 253 executeSoon(function () { 254 testGenerator.next(); 255 }); 256 }; 257 258 self.continueToNextStepSync = function () { 259 testGenerator.next(); 260 }; 261 262 self._clearAllDatabasesCallback = undefined; 263 self.clearAllDatabases = function (_callback_) { 264 self._clearAllDatabasesCallback = _callback_; 265 self.postMessage({ op: "clearAllDatabases" }); 266 }; 267 268 self.onerror = function (_message_, _file_, _line_) { 269 ok( 270 false, 271 "Worker: uncaught exception [" + 272 _file_ + 273 ":" + 274 _line_ + 275 "]: '" + 276 _message_ + 277 "'" 278 ); 279 self.finishTest(); 280 self.close(); 281 return true; 282 }; 283 284 self.onmessage = function (_event_) { 285 let message = _event_.data; 286 switch (message.op) { 287 case "load": 288 info("Worker: loading " + JSON.stringify(message.files)); 289 self.importScripts(message.files); 290 self.postMessage({ op: "loaded" }); 291 break; 292 293 case "start": 294 executeSoon(function () { 295 info("Worker: starting tests"); 296 testGenerator = testSteps(); 297 testGenerator.next(); 298 }); 299 break; 300 301 case "clearAllDatabasesDone": 302 info("Worker: all databases are cleared"); 303 if (self._clearAllDatabasesCallback) { 304 self._clearAllDatabasesCallback(); 305 } 306 break; 307 308 default: 309 throw new Error( 310 "Received a bad message from parent: " + JSON.stringify(message) 311 ); 312 } 313 }; 314 315 self.postMessage({ op: "ready" }); 316 }