test-array.js (6130B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // This file expects utils.js to be included in its scope 6 /* import-globals-from ./util.js */ 7 var MOCHITEST = false; 8 9 function Test(name, test) { 10 this.name = name; 11 this.startTime = null; 12 this.endTime = null; 13 this.result = null; 14 this.row = null; 15 16 this.run = function () { 17 // Note the start time 18 this.startTime = new Date(); 19 // Run the test 20 try { 21 test.call(this); 22 } catch (e) { 23 console.log(e); 24 console.log(e.stack); 25 this.complete(false); 26 } 27 }; 28 29 this.memcmp_complete = function (x, y) { 30 var passfail = util.memcmp(x, y); 31 if (!passfail) { 32 console.log("expected: " + util.abv2hex(x)); 33 console.log(" got: " + util.abv2hex(y)); 34 } 35 this.complete(passfail); 36 }; 37 38 this.complete = function (result) { 39 if (MOCHITEST) { 40 ok(result, this.name); 41 } 42 43 // Note the end time 44 this.endTime = new Date(); 45 // Set result 46 this.result = result; 47 // Re-draw the row 48 this.draw(); 49 this.next(); 50 }; 51 52 this.next = function () { 53 if (this.oncomplete) { 54 this.oncomplete(); 55 } 56 }; 57 58 this.setRow = function (id) { 59 this.row = document.getElementById(id).getElementsByTagName("td"); 60 }; 61 62 this.draw = function () { 63 if (!this.row) { 64 return; 65 } 66 67 // Print the name of the test 68 if (this.name) { 69 this.row[0].textContent = this.name; 70 var that = this; 71 this.row[0].onclick = function () { 72 that.run(); 73 }; 74 } else { 75 this.row[0] = ""; 76 } 77 78 // Print the result of the test 79 if (this.result === true) { 80 this.row[1].className = "pass"; 81 this.row[1].innerHTML = "PASS"; 82 } else if (this.result === false) { 83 this.row[1].className = "fail"; 84 this.row[1].innerHTML = "FAIL"; 85 } else { 86 // this.row[1].innerHTML = ""; 87 this.row[1].textContent = this.result; 88 } 89 90 // Print the elapsed time, if known 91 if (this.startTime && this.endTime) { 92 this.row[2].textContent = this.endTime - this.startTime + " ms"; 93 } else { 94 this.row[2].innerHTML = ""; 95 } 96 }; 97 } 98 99 function WorkerTest(worker, name, test) { 100 this.name = `${name} (Worker)`; 101 this.startTime = null; 102 this.endTime = null; 103 this.result = null; 104 this.row = null; 105 106 this.run = function () { 107 // Note the start time 108 this.startTime = new Date(); 109 110 // Send the test code to the worker. 111 worker.postMessage(test.toString()); 112 113 // We expect only boolean responses from the worker script. 114 worker.onmessage = e => this.complete(e.data); 115 worker.onerror = () => this.complete(false); 116 }; 117 118 var base = new Test(name, test); 119 120 // Inherit what we need from the |Test| class. We can't simply use its 121 // prototype as Test is just a function that can be used like a constructor. 122 for (var method of ["draw", "setRow", "next", "complete"]) { 123 this[method] = base[method].bind(this); 124 } 125 } 126 127 var TestArray = { 128 tests: [], 129 table: null, 130 passSpan: null, 131 failSpan: null, 132 pendingSpan: null, 133 pass: 0, 134 fail: 0, 135 pending: 0, 136 currTest: 0, 137 worker: new Worker("test-worker.js"), 138 139 addTest(name, testFn) { 140 // Give it a reference to the array 141 var test = new Test(name, testFn); 142 test.ta = this; 143 144 // Add test to tests 145 this.tests.push(test); 146 147 // Run the test in a worker too. 148 this.tests.push(new WorkerTest(this.worker, name, testFn)); 149 }, 150 151 updateSummary() { 152 this.pass = this.fail = this.pending = 0; 153 for (var i = 0; i < this.tests.length; ++i) { 154 if (this.tests[i].result === true) { 155 this.pass++; 156 } 157 if (this.tests[i].result === false) { 158 this.fail++; 159 } 160 if (this.tests[i].result == null) { 161 this.pending++; 162 } 163 } 164 this.passSpan.textContent = this.pass; 165 this.failSpan.textContent = this.fail; 166 this.pendingSpan.textContent = this.pending; 167 }, 168 169 load() { 170 // Grab reference to table and summary numbers 171 this.table = document.getElementById("results"); 172 this.passSpan = document.getElementById("passN"); 173 this.failSpan = document.getElementById("failN"); 174 this.pendingSpan = document.getElementById("pendingN"); 175 176 // Populate everything initially 177 this.updateSummary(); 178 for (var i = 0; i < this.tests.length; ++i) { 179 var tr = document.createElement("tr"); 180 tr.id = "test" + i; 181 tr.appendChild(document.createElement("td")); 182 tr.appendChild(document.createElement("td")); 183 tr.appendChild(document.createElement("td")); 184 this.table.appendChild(tr); 185 this.tests[i].setRow(tr.id); 186 this.tests[i].draw(); 187 } 188 }, 189 190 run() { 191 this.currTest = 0; 192 this.runNextTest(); 193 }, 194 195 runNextTest() { 196 this.updateSummary(); 197 var i = this.currTest++; 198 if (i >= this.tests.length) { 199 if (MOCHITEST) { 200 SimpleTest.finish(); 201 } 202 return; 203 } 204 205 var self = this; 206 this.tests[i].oncomplete = function () { 207 self.runNextTest(); 208 }; 209 this.tests[i].run(); 210 }, 211 }; 212 213 if (window.addEventListener) { 214 window.addEventListener("load", function () { 215 TestArray.load(); 216 }); 217 } else { 218 window.attachEvent("onload", function () { 219 TestArray.load(); 220 }); 221 } 222 223 function start() { 224 TestArray.run(); 225 } 226 227 MOCHITEST = "SimpleTest" in window; 228 if (MOCHITEST) { 229 SimpleTest.waitForExplicitFinish(); 230 SimpleTest.requestLongerTimeout(2); 231 window.addEventListener("load", function () { 232 SimpleTest.waitForFocus(start); 233 }); 234 } 235 236 function error(test) { 237 return function (x) { 238 console.log("ERROR :: " + x); 239 test.complete(false); 240 throw x; 241 }; 242 } 243 244 function complete(test, valid) { 245 return function (x) { 246 console.log("COMPLETE"); 247 console.log(x); 248 if (valid) { 249 test.complete(valid(x)); 250 } else { 251 test.complete(true); 252 } 253 }; 254 } 255 256 function memcmp_complete(test, value) { 257 return function (x) { 258 console.log("COMPLETE"); 259 console.log(x); 260 test.memcmp_complete(value, x); 261 }; 262 }