test_sync.js (8516B)
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 file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 const { 6 DebounceCallback, 7 PollPromise, 8 Sleep, 9 waitForMessage, 10 waitForObserverTopic, 11 } = ChromeUtils.importESModule( 12 "chrome://remote/content/marionette/sync.sys.mjs" 13 ); 14 15 /** 16 * Mimic a message manager for sending messages. 17 */ 18 class MessageManager { 19 constructor() { 20 this.func = null; 21 this.message = null; 22 } 23 24 addMessageListener(message, func) { 25 this.func = func; 26 this.message = message; 27 } 28 29 removeMessageListener() { 30 this.func = null; 31 this.message = null; 32 } 33 34 send(message, data) { 35 if (this.func) { 36 this.func({ 37 data, 38 message, 39 target: this, 40 }); 41 } 42 } 43 } 44 45 /** 46 * Mimics nsITimer, but instead of using a system clock you can 47 * preprogram it to invoke the callback after a given number of ticks. 48 */ 49 class MockTimer { 50 constructor(ticksBeforeFiring) { 51 this.goal = ticksBeforeFiring; 52 this.ticks = 0; 53 this.cancelled = false; 54 } 55 56 initWithCallback(cb) { 57 this.ticks++; 58 if (this.ticks >= this.goal) { 59 cb(); 60 } 61 } 62 63 cancel() { 64 this.cancelled = true; 65 } 66 } 67 68 add_task(function test_PollPromise_funcTypes() { 69 for (let type of ["foo", 42, null, undefined, true, [], {}]) { 70 Assert.throws(() => new PollPromise(type), /TypeError/); 71 } 72 new PollPromise(() => {}); 73 new PollPromise(function () {}); 74 }); 75 76 add_task(function test_PollPromise_timeoutTypes() { 77 for (let timeout of ["foo", true, [], {}]) { 78 Assert.throws(() => new PollPromise(() => {}, { timeout }), /TypeError/); 79 } 80 for (let timeout of [1.2, -1]) { 81 Assert.throws(() => new PollPromise(() => {}, { timeout }), /RangeError/); 82 } 83 for (let timeout of [null, undefined, 42]) { 84 new PollPromise(resolve => resolve(1), { timeout }); 85 } 86 }); 87 88 add_task(function test_PollPromise_intervalTypes() { 89 for (let interval of ["foo", null, true, [], {}]) { 90 Assert.throws(() => new PollPromise(() => {}, { interval }), /TypeError/); 91 } 92 for (let interval of [1.2, -1]) { 93 Assert.throws(() => new PollPromise(() => {}, { interval }), /RangeError/); 94 } 95 new PollPromise(() => {}, { interval: 42 }); 96 }); 97 98 add_task(async function test_PollPromise_retvalTypes() { 99 for (let typ of [true, false, "foo", 42, [], {}]) { 100 strictEqual(typ, await new PollPromise(resolve => resolve(typ))); 101 } 102 }); 103 104 add_task(async function test_PollPromise_rethrowError() { 105 let nevals = 0; 106 let err; 107 try { 108 await PollPromise(() => { 109 ++nevals; 110 throw new Error(); 111 }); 112 } catch (e) { 113 err = e; 114 } 115 equal(1, nevals); 116 ok(err instanceof Error); 117 }); 118 119 add_task(async function test_PollPromise_noTimeout() { 120 let nevals = 0; 121 await new PollPromise((resolve, reject) => { 122 ++nevals; 123 nevals < 100 ? reject() : resolve(); 124 }); 125 equal(100, nevals); 126 }); 127 128 add_task(async function test_PollPromise_zeroTimeout() { 129 // run at least once when timeout is 0 130 let nevals = 0; 131 let start = new Date().getTime(); 132 await new PollPromise( 133 (resolve, reject) => { 134 ++nevals; 135 reject(); 136 }, 137 { timeout: 0 } 138 ); 139 let end = new Date().getTime(); 140 equal(1, nevals); 141 less(end - start, 500); 142 }); 143 144 add_task(async function test_PollPromise_timeoutElapse() { 145 let nevals = 0; 146 let start = new Date().getTime(); 147 await new PollPromise( 148 (resolve, reject) => { 149 ++nevals; 150 reject(); 151 }, 152 { timeout: 100 } 153 ); 154 let end = new Date().getTime(); 155 lessOrEqual(nevals, 11); 156 greaterOrEqual(end - start, 100); 157 }); 158 159 add_task(async function test_PollPromise_interval() { 160 let nevals = 0; 161 await new PollPromise( 162 (resolve, reject) => { 163 ++nevals; 164 reject(); 165 }, 166 { timeout: 100, interval: 100 } 167 ); 168 equal(2, nevals); 169 }); 170 171 add_task(async function test_Sleep() { 172 await Sleep(0); 173 for (let type of ["foo", true, null, undefined]) { 174 Assert.throws(() => new Sleep(type), /TypeError/); 175 } 176 Assert.throws(() => new Sleep(1.2), /RangeError/); 177 Assert.throws(() => new Sleep(-1), /RangeError/); 178 }); 179 180 add_task(function test_DebounceCallback_constructor() { 181 for (let cb of [42, "foo", true, null, undefined, [], {}]) { 182 Assert.throws(() => new DebounceCallback(cb), /TypeError/); 183 } 184 for (let timeout of ["foo", true, [], {}, () => {}]) { 185 Assert.throws( 186 () => new DebounceCallback(() => {}, { timeout }), 187 /TypeError/ 188 ); 189 } 190 for (let timeout of [-1, 2.3, NaN]) { 191 Assert.throws( 192 () => new DebounceCallback(() => {}, { timeout }), 193 /RangeError/ 194 ); 195 } 196 }); 197 198 add_task(async function test_DebounceCallback_repeatedCallback() { 199 let uniqueEvent = {}; 200 let ncalls = 0; 201 202 let cb = ev => { 203 ncalls++; 204 equal(ev, uniqueEvent); 205 }; 206 let debouncer = new DebounceCallback(cb); 207 debouncer.timer = new MockTimer(3); 208 209 // flood the debouncer with events, 210 // we only expect the last one to fire 211 debouncer.handleEvent(uniqueEvent); 212 debouncer.handleEvent(uniqueEvent); 213 debouncer.handleEvent(uniqueEvent); 214 215 equal(ncalls, 1); 216 ok(debouncer.timer.cancelled); 217 }); 218 219 add_task(async function test_waitForMessage_messageManagerAndMessageTypes() { 220 let messageManager = new MessageManager(); 221 222 for (let manager of ["foo", 42, null, undefined, true, [], {}]) { 223 Assert.throws(() => waitForMessage(manager, "message"), /TypeError/); 224 } 225 226 for (let message of [42, null, undefined, true, [], {}]) { 227 Assert.throws(() => waitForMessage(messageManager, message), /TypeError/); 228 } 229 230 let data = { foo: "bar" }; 231 let sent = waitForMessage(messageManager, "message"); 232 messageManager.send("message", data); 233 equal(data, await sent); 234 }); 235 236 add_task(async function test_waitForMessage_checkFnTypes() { 237 let messageManager = new MessageManager(); 238 239 for (let checkFn of ["foo", 42, true, [], {}]) { 240 Assert.throws( 241 () => waitForMessage(messageManager, "message", { checkFn }), 242 /TypeError/ 243 ); 244 } 245 246 let data1 = { notFoo: "bar" }; 247 let data2 = { foo: "bar" }; 248 249 for (let checkFn of [null, undefined, msg => "foo" in msg.data]) { 250 let expected_data = checkFn == null ? data1 : data2; 251 252 messageManager = new MessageManager(); 253 let sent = waitForMessage(messageManager, "message", { checkFn }); 254 messageManager.send("message", data1); 255 messageManager.send("message", data2); 256 equal(expected_data, await sent); 257 } 258 }); 259 260 add_task(async function test_waitForObserverTopic_topicTypes() { 261 for (let topic of [42, null, undefined, true, [], {}]) { 262 Assert.throws(() => waitForObserverTopic(topic), /TypeError/); 263 } 264 265 let data = { foo: "bar" }; 266 let sent = waitForObserverTopic("message"); 267 Services.obs.notifyObservers(this, "message", data); 268 let result = await sent; 269 equal(this, result.subject); 270 equal(data, result.data); 271 }); 272 273 add_task(async function test_waitForObserverTopic_checkFnTypes() { 274 for (let checkFn of ["foo", 42, true, [], {}]) { 275 Assert.throws( 276 () => waitForObserverTopic("message", { checkFn }), 277 /TypeError/ 278 ); 279 } 280 281 let data1 = { notFoo: "bar" }; 282 let data2 = { foo: "bar" }; 283 284 for (let checkFn of [null, undefined, (subject, data) => data == data2]) { 285 let expected_data = checkFn == null ? data1 : data2; 286 287 let sent = waitForObserverTopic("message"); 288 Services.obs.notifyObservers(this, "message", data1); 289 Services.obs.notifyObservers(this, "message", data2); 290 let result = await sent; 291 equal(expected_data, result.data); 292 } 293 }); 294 295 add_task(async function test_waitForObserverTopic_timeoutTypes() { 296 for (let timeout of ["foo", true, [], {}]) { 297 Assert.throws( 298 () => waitForObserverTopic("message", { timeout }), 299 /TypeError/ 300 ); 301 } 302 for (let timeout of [1.2, -1]) { 303 Assert.throws( 304 () => waitForObserverTopic("message", { timeout }), 305 /RangeError/ 306 ); 307 } 308 for (let timeout of [null, undefined, 42]) { 309 let data = { foo: "bar" }; 310 let sent = waitForObserverTopic("message", { timeout }); 311 Services.obs.notifyObservers(this, "message", data); 312 let result = await sent; 313 equal(this, result.subject); 314 equal(data, result.data); 315 } 316 }); 317 318 add_task(async function test_waitForObserverTopic_timeoutElapse() { 319 try { 320 await waitForObserverTopic("message", { timeout: 0 }); 321 ok(false, "Expected Timeout error not raised"); 322 } catch (e) { 323 ok( 324 e.message.includes("waitForObserverTopic timed out after"), 325 "Expected error received" 326 ); 327 } 328 });