toolkit/modules/tests/xpcshell/test_task.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:5b6cc5b40349
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
3
4 /**
5 * This file tests the Task.jsm module.
6 */
7
8 ////////////////////////////////////////////////////////////////////////////////
9 /// Globals
10
11 const Cc = Components.classes;
12 const Ci = Components.interfaces;
13 const Cu = Components.utils;
14 const Cr = Components.results;
15
16 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
17
18 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
19 "resource://gre/modules/Promise.jsm");
20 XPCOMUtils.defineLazyModuleGetter(this, "Services",
21 "resource://gre/modules/Services.jsm");
22 XPCOMUtils.defineLazyModuleGetter(this, "Task",
23 "resource://gre/modules/Task.jsm");
24
25 /**
26 * Returns a promise that will be resolved with the given value, when an event
27 * posted on the event loop of the main thread is processed.
28 */
29 function promiseResolvedLater(aValue) {
30 let deferred = Promise.defer();
31 Services.tm.mainThread.dispatch(function () deferred.resolve(aValue),
32 Ci.nsIThread.DISPATCH_NORMAL);
33 return deferred.promise;
34 }
35
36 ////////////////////////////////////////////////////////////////////////////////
37 /// Tests
38
39 function run_test()
40 {
41 run_next_test();
42 }
43
44 add_test(function test_normal()
45 {
46 Task.spawn(function () {
47 let result = yield Promise.resolve("Value");
48 for (let i = 0; i < 3; i++) {
49 result += yield promiseResolvedLater("!");
50 }
51 throw new Task.Result("Task result: " + result);
52 }).then(function (result) {
53 do_check_eq("Task result: Value!!!", result);
54 run_next_test();
55 }, function (ex) {
56 do_throw("Unexpected error: " + ex);
57 });
58 });
59
60 add_test(function test_exceptions()
61 {
62 Task.spawn(function () {
63 try {
64 yield Promise.reject("Rejection result by promise.");
65 do_throw("Exception expected because the promise was rejected.");
66 } catch (ex) {
67 // We catch this exception now, we will throw a different one later.
68 do_check_eq("Rejection result by promise.", ex);
69 }
70 throw new Error("Exception uncaught by task.");
71 }).then(function (result) {
72 do_throw("Unexpected success!");
73 }, function (ex) {
74 do_check_eq("Exception uncaught by task.", ex.message);
75 run_next_test();
76 });
77 });
78
79 add_test(function test_recursion()
80 {
81 function task_fibonacci(n) {
82 throw new Task.Result(n < 2 ? n : (yield task_fibonacci(n - 1)) +
83 (yield task_fibonacci(n - 2)));
84 };
85
86 Task.spawn(task_fibonacci(6)).then(function (result) {
87 do_check_eq(8, result);
88 run_next_test();
89 }, function (ex) {
90 do_throw("Unexpected error: " + ex);
91 });
92 });
93
94 add_test(function test_spawn_primitive()
95 {
96 function fibonacci(n) {
97 return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
98 };
99
100 // Polymorphism between task and non-task functions (see "test_recursion").
101 Task.spawn(fibonacci(6)).then(function (result) {
102 do_check_eq(8, result);
103 run_next_test();
104 }, function (ex) {
105 do_throw("Unexpected error: " + ex);
106 });
107 });
108
109 add_test(function test_spawn_function()
110 {
111 Task.spawn(function () {
112 return "This is not a generator.";
113 }).then(function (result) {
114 do_check_eq("This is not a generator.", result);
115 run_next_test();
116 }, function (ex) {
117 do_throw("Unexpected error: " + ex);
118 });
119 });
120
121 add_test(function test_spawn_function_this()
122 {
123 Task.spawn(function () {
124 return this;
125 }).then(function (result) {
126 // Since the task function wasn't defined in strict mode, its "this" object
127 // should be the same as the "this" object in this function, i.e. the global
128 // object.
129 do_check_eq(result, this);
130 run_next_test();
131 }, function (ex) {
132 do_throw("Unexpected error: " + ex);
133 });
134 });
135
136 add_test(function test_spawn_function_this_strict()
137 {
138 "use strict";
139 Task.spawn(function () {
140 return this;
141 }).then(function (result) {
142 // Since the task function was defined in strict mode, its "this" object
143 // should be undefined.
144 do_check_eq(typeof(result), "undefined");
145 run_next_test();
146 }, function (ex) {
147 do_throw("Unexpected error: " + ex);
148 });
149 });
150
151 add_test(function test_spawn_function_returning_promise()
152 {
153 Task.spawn(function () {
154 return promiseResolvedLater("Resolution value.");
155 }).then(function (result) {
156 do_check_eq("Resolution value.", result);
157 run_next_test();
158 }, function (ex) {
159 do_throw("Unexpected error: " + ex);
160 });
161 });
162
163 add_test(function test_spawn_function_exceptions()
164 {
165 Task.spawn(function () {
166 throw new Error("Exception uncaught by task.");
167 }).then(function (result) {
168 do_throw("Unexpected success!");
169 }, function (ex) {
170 do_check_eq("Exception uncaught by task.", ex.message);
171 run_next_test();
172 });
173 });
174
175 add_test(function test_spawn_function_taskresult()
176 {
177 Task.spawn(function () {
178 throw new Task.Result("Task result");
179 }).then(function (result) {
180 do_check_eq("Task result", result);
181 run_next_test();
182 }, function (ex) {
183 do_throw("Unexpected error: " + ex);
184 });
185 });
186
187 add_test(function test_yielded_undefined()
188 {
189 Task.spawn(function () {
190 yield;
191 throw new Task.Result("We continued correctly.");
192 }).then(function (result) {
193 do_check_eq("We continued correctly.", result);
194 run_next_test();
195 }, function (ex) {
196 do_throw("Unexpected error: " + ex);
197 });
198 });
199
200 add_test(function test_yielded_primitive()
201 {
202 Task.spawn(function () {
203 throw new Task.Result("Primitive " + (yield "value."));
204 }).then(function (result) {
205 do_check_eq("Primitive value.", result);
206 run_next_test();
207 }, function (ex) {
208 do_throw("Unexpected error: " + ex);
209 });
210 });
211
212 add_test(function test_star_normal()
213 {
214 Task.spawn(function* () {
215 let result = yield Promise.resolve("Value");
216 for (let i = 0; i < 3; i++) {
217 result += yield promiseResolvedLater("!");
218 }
219 return "Task result: " + result;
220 }).then(function (result) {
221 do_check_eq("Task result: Value!!!", result);
222 run_next_test();
223 }, function (ex) {
224 do_throw("Unexpected error: " + ex);
225 });
226 });
227
228 add_test(function test_star_exceptions()
229 {
230 Task.spawn(function* () {
231 try {
232 yield Promise.reject("Rejection result by promise.");
233 do_throw("Exception expected because the promise was rejected.");
234 } catch (ex) {
235 // We catch this exception now, we will throw a different one later.
236 do_check_eq("Rejection result by promise.", ex);
237 }
238 throw new Error("Exception uncaught by task.");
239 }).then(function (result) {
240 do_throw("Unexpected success!");
241 }, function (ex) {
242 do_check_eq("Exception uncaught by task.", ex.message);
243 run_next_test();
244 });
245 });
246
247 add_test(function test_star_recursion()
248 {
249 function* task_fibonacci(n) {
250 return n < 2 ? n : (yield task_fibonacci(n - 1)) +
251 (yield task_fibonacci(n - 2));
252 };
253
254 Task.spawn(task_fibonacci(6)).then(function (result) {
255 do_check_eq(8, result);
256 run_next_test();
257 }, function (ex) {
258 do_throw("Unexpected error: " + ex);
259 });
260 });
261
262 add_test(function test_mixed_legacy_and_star()
263 {
264 Task.spawn(function* () {
265 return yield (function() {
266 throw new Task.Result(yield 5);
267 })();
268 }).then(function (result) {
269 do_check_eq(5, result);
270 run_next_test();
271 }, function (ex) {
272 do_throw("Unexpected error: " + ex);
273 });
274 });
275
276 add_test(function test_async_function_from_generator()
277 {
278 Task.spawn(function* () {
279 let object = {
280 asyncFunction: Task.async(function* (param) {
281 do_check_eq(this, object);
282 return param;
283 })
284 };
285
286 // Ensure the async function returns a promise that resolves as expected.
287 do_check_eq((yield object.asyncFunction(1)), 1);
288
289 // Ensure a second call to the async function also returns such a promise.
290 do_check_eq((yield object.asyncFunction(3)), 3);
291 }).then(function () {
292 run_next_test();
293 }, function (ex) {
294 do_throw("Unexpected error: " + ex);
295 });
296 });
297
298 add_test(function test_async_function_from_function()
299 {
300 Task.spawn(function* () {
301 return Task.spawn(function* () {
302 let object = {
303 asyncFunction: Task.async(function (param) {
304 do_check_eq(this, object);
305 return param;
306 })
307 };
308
309 // Ensure the async function returns a promise that resolves as expected.
310 do_check_eq((yield object.asyncFunction(5)), 5);
311
312 // Ensure a second call to the async function also returns such a promise.
313 do_check_eq((yield object.asyncFunction(7)), 7);
314 });
315 }).then(function () {
316 run_next_test();
317 }, function (ex) {
318 do_throw("Unexpected error: " + ex);
319 });
320 });
321
322 add_test(function test_async_function_that_throws_rejects_promise()
323 {
324 Task.spawn(function* () {
325 let object = {
326 asyncFunction: Task.async(function* () {
327 throw "Rejected!";
328 })
329 };
330
331 yield object.asyncFunction();
332 }).then(function () {
333 do_throw("unexpected success calling async function that throws error");
334 }, function (ex) {
335 do_check_eq(ex, "Rejected!");
336 run_next_test();
337 });
338 });
339
340 add_test(function test_async_return_function()
341 {
342 Task.spawn(function* () {
343 // Ensure an async function that returns a function resolves to the function
344 // itself instead of calling the function and resolving to its return value.
345 return Task.spawn(function* () {
346 let returnValue = function () {
347 return "These aren't the droids you're looking for.";
348 };
349
350 let asyncFunction = Task.async(function () {
351 return returnValue;
352 });
353
354 do_check_eq((yield asyncFunction()), returnValue);
355 });
356 }).then(function () {
357 run_next_test();
358 }, function (ex) {
359 do_throw("Unexpected error: " + ex);
360 });
361 });
362
363 add_test(function test_async_throw_argument_not_function()
364 {
365 Task.spawn(function* () {
366 // Ensure Task.async throws if its aTask argument is not a function.
367 Assert.throws(() => Task.async("not a function"),
368 /aTask argument must be a function/);
369 }).then(function () {
370 run_next_test();
371 }, function (ex) {
372 do_throw("Unexpected error: " + ex);
373 });
374 });
375
376 add_test(function test_async_throw_on_function_in_place_of_promise()
377 {
378 Task.spawn(function* () {
379 // Ensure Task.spawn throws if passed an async function.
380 Assert.throws(() => Task.spawn(Task.async(function* () {})),
381 /Cannot use an async function in place of a promise/);
382 }).then(function () {
383 run_next_test();
384 }, function (ex) {
385 do_throw("Unexpected error: " + ex);
386 });
387 });

mercurial