1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { PollPromise } = ChromeUtils.import("chrome://remote/content/Sync.jsm");
/**
* Mimic a DOM node for listening for events.
*/
class MockElement {
constructor() {
this.capture = false;
this.func = null;
this.eventName = null;
this.untrusted = false;
}
addEventListener(name, func, capture, untrusted) {
this.eventName = name;
this.func = func;
if (capture != null) {
this.capture = capture;
}
if (untrusted != null) {
this.untrusted = untrusted;
}
}
click() {
if (this.func) {
let details = {
capture: this.capture,
target: this,
type: this.eventName,
untrusted: this.untrusted,
};
this.func(details);
}
}
removeEventListener(name, func) {
this.capture = false;
this.func = null;
this.eventName = null;
this.untrusted = false;
}
}
/**
* Mimic a message manager for sending messages.
*/
class MessageManager {
constructor() {
this.func = null;
this.message = null;
}
addMessageListener(message, func) {
this.func = func;
this.message = message;
}
removeMessageListener(message) {
this.func = null;
this.message = null;
}
send(message, data) {
if (this.func) {
this.func({
data,
message,
target: this,
});
}
}
}
/**
* Mimics nsITimer, but instead of using a system clock you can
* preprogram it to invoke the callback after a given number of ticks.
*/
class MockTimer {
constructor(ticksBeforeFiring) {
this.goal = ticksBeforeFiring;
this.ticks = 0;
this.cancelled = false;
}
initWithCallback(cb, timeout, type) {
this.ticks++;
if (this.ticks >= this.goal) {
cb();
}
}
cancel() {
this.cancelled = true;
}
}
add_test(function test_executeSoon_callback() {
// executeSoon() is already defined for xpcshell in head.js. As such import
// our implementation into a custom namespace.
let sync = {};
ChromeUtils.import("chrome://remote/content/Sync.jsm", sync);
for (let func of ["foo", null, true, [], {}]) {
Assert.throws(() => sync.executeSoon(func), /TypeError/);
}
let a;
sync.executeSoon(() => {
a = 1;
});
executeSoon(() => equal(1, a));
run_next_test();
});
add_test(function test_PollPromise_funcTypes() {
for (let type of ["foo", 42, null, undefined, true, [], {}]) {
Assert.throws(() => new PollPromise(type), /TypeError/);
}
new PollPromise(() => {});
new PollPromise(function() {});
run_next_test();
});
add_test(function test_PollPromise_timeoutTypes() {
for (let timeout of ["foo", true, [], {}]) {
Assert.throws(() => new PollPromise(() => {}, { timeout }), /TypeError/);
}
for (let timeout of [1.2, -1]) {
Assert.throws(() => new PollPromise(() => {}, { timeout }), /RangeError/);
}
for (let timeout of [null, undefined, 42]) {
new PollPromise(resolve => resolve(1), { timeout });
}
run_next_test();
});
add_test(function test_PollPromise_intervalTypes() {
for (let interval of ["foo", null, true, [], {}]) {
Assert.throws(() => new PollPromise(() => {}, { interval }), /TypeError/);
}
for (let interval of [1.2, -1]) {
Assert.throws(() => new PollPromise(() => {}, { interval }), /RangeError/);
}
new PollPromise(() => {}, { interval: 42 });
run_next_test();
});
add_task(async function test_PollPromise_retvalTypes() {
for (let typ of [true, false, "foo", 42, [], {}]) {
strictEqual(typ, await new PollPromise(resolve => resolve(typ)));
}
});
add_task(async function test_PollPromise_rethrowError() {
let nevals = 0;
let err;
try {
await PollPromise(() => {
++nevals;
throw new Error();
});
} catch (e) {
err = e;
}
equal(1, nevals);
ok(err instanceof Error);
});
add_task(async function test_PollPromise_noTimeout() {
let nevals = 0;
await new PollPromise((resolve, reject) => {
++nevals;
nevals < 100 ? reject() : resolve();
});
equal(100, nevals);
});
add_task(async function test_PollPromise_zeroTimeout() {
// run at least once when timeout is 0
let nevals = 0;
let start = new Date().getTime();
await new PollPromise(
(resolve, reject) => {
++nevals;
reject();
},
{ timeout: 0 }
);
let end = new Date().getTime();
equal(1, nevals);
less(end - start, 500);
});
add_task(async function test_PollPromise_timeoutElapse() {
let nevals = 0;
let start = new Date().getTime();
await new PollPromise(
(resolve, reject) => {
++nevals;
reject();
},
{ timeout: 100 }
);
let end = new Date().getTime();
lessOrEqual(nevals, 11);
greaterOrEqual(end - start, 100);
});
add_task(async function test_PollPromise_interval() {
let nevals = 0;
await new PollPromise(
(resolve, reject) => {
++nevals;
reject();
},
{ timeout: 100, interval: 100 }
);
equal(2, nevals);
});
|