Commit | Line | Data |
---|---|---|
6a1aa64f DV |
1 | <html> |
2 | <head> | |
3 | <script type="text/javascript" src="../MochiKit/Base.js"></script> | |
4 | <script type="text/javascript" src="../MochiKit/Async.js"></script> | |
5 | <script type="text/javascript" src="../MochiKit/Iter.js"></script> | |
6 | <script type="text/javascript" src="../MochiKit/DOM.js"></script> | |
7 | <script type="text/javascript" src="../MochiKit/Style.js"></script> | |
8 | <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script> | |
9 | <link rel="stylesheet" type="text/css" href="SimpleTest/test.css"> | |
10 | </head> | |
11 | <body> | |
12 | ||
13 | <pre id="test"> | |
14 | <script type="text/javascript"> | |
15 | try { | |
16 | ||
17 | var increment = function (res) { | |
18 | return res + 1; | |
19 | } | |
20 | ||
21 | var throwStuff = function (res) { | |
22 | throw new GenericError(res); | |
23 | } | |
24 | ||
25 | var catchStuff = function (res) { | |
26 | return res.message; | |
27 | } | |
28 | ||
29 | var returnError = function (res) { | |
30 | return new GenericError(res); | |
31 | } | |
32 | ||
33 | var anythingOkCallback = function (msg) { | |
34 | return function (res) { | |
35 | ok(true, msg); | |
36 | return res; | |
37 | } | |
38 | } | |
39 | ||
40 | var testEqCallback = function () { | |
41 | /* | |
42 | sort of emulate how deferreds work in Twisted | |
43 | for "convenient" testing | |
44 | */ | |
45 | var args = []; | |
46 | for (var i = 0; i < arguments.length; i++) { | |
47 | args.push(arguments[i]); | |
48 | } | |
49 | return function (res) { | |
50 | var nargs = args.slice(); | |
51 | nargs.unshift(res); | |
52 | is.apply(this, nargs); | |
53 | return res; | |
54 | } | |
55 | } | |
56 | ||
57 | var neverHappen = function (d) { | |
58 | ok(false, "this should never happen"); | |
59 | } | |
60 | ||
61 | /* | |
62 | Test normal Deferred operation | |
63 | */ | |
64 | var d = new Deferred(); | |
65 | d.addCallback(testEqCallback(1, "pre-deferred callback")); | |
66 | d.callback(1); | |
67 | d.addCallback(increment); | |
68 | d.addCallback(testEqCallback(2, "post-deferred callback")); | |
69 | d.addCallback(throwStuff); | |
70 | d.addCallback(neverHappen); | |
71 | d.addErrback(catchStuff); | |
72 | d.addCallback(testEqCallback(2, "throw -> err, catch -> success")); | |
73 | d.addCallback(returnError); | |
74 | d.addCallback(neverHappen); | |
75 | d.addErrback(catchStuff); | |
76 | d.addCallback(testEqCallback(2, "return -> err, catch -> succcess")); | |
77 | ||
78 | /* | |
79 | Test Deferred cancellation | |
80 | */ | |
81 | var cancelled = function (d) { | |
82 | ok(true, "canceller called!"); | |
83 | } | |
84 | ||
85 | var cancelledError = function (res) { | |
86 | ok(res instanceof CancelledError, "CancelledError here"); | |
87 | } | |
88 | ||
89 | d = new Deferred(cancelled); | |
90 | d.addCallback(neverHappen); | |
91 | d.addErrback(cancelledError); | |
92 | d.cancel(); | |
93 | ||
94 | /* | |
95 | Test succeed / fail | |
96 | */ | |
97 | ||
98 | d = succeed(1).addCallback(testEqCallback(1, "succeed")); | |
99 | ||
100 | // default error | |
101 | d = fail().addCallback(neverHappen); | |
102 | d = d.addErrback(anythingOkCallback("default fail")); | |
103 | ||
104 | // default wrapped error | |
105 | d = fail("web taco").addCallback(neverHappen).addErrback(catchStuff); | |
106 | d = d.addCallback(testEqCallback("web taco", "wrapped fail")); | |
107 | ||
108 | // default unwrapped error | |
109 | d = fail(new GenericError("ugh")).addCallback(neverHappen).addErrback(catchStuff); | |
110 | d = d.addCallback(testEqCallback("ugh", "unwrapped fail")); | |
111 | ||
112 | /* | |
113 | Test deferred dependencies | |
114 | */ | |
115 | ||
116 | var deferredIncrement = function (res) { | |
117 | var rval = succeed(res); | |
118 | rval.addCallback(increment); | |
119 | return rval; | |
120 | } | |
121 | ||
122 | d = succeed(1).addCallback(deferredIncrement); | |
123 | d = d.addCallback(testEqCallback(2, "dependent deferred succeed")); | |
124 | ||
125 | var deferredFailure = function (res) { | |
126 | return fail(res); | |
127 | } | |
128 | ||
129 | d = succeed("ugh").addCallback(deferredFailure).addErrback(catchStuff); | |
130 | d = d.addCallback(testEqCallback("ugh", "dependent deferred fail")); | |
131 | ||
132 | /* | |
133 | Test double-calling, double-failing, etc. | |
134 | */ | |
135 | try { | |
136 | succeed(1).callback(2); | |
137 | neverHappen(); | |
138 | } catch (e) { | |
139 | ok(e instanceof AlreadyCalledError, "double-call"); | |
140 | } | |
141 | try { | |
142 | fail(1).errback(2); | |
143 | neverHappen(); | |
144 | } catch (e) { | |
145 | ok(e instanceof AlreadyCalledError, "double-fail"); | |
146 | } | |
147 | try { | |
148 | d = succeed(1); | |
149 | d.cancel(); | |
150 | d = d.callback(2); | |
151 | ok(true, "swallowed one callback, no canceller"); | |
152 | d.callback(3); | |
153 | neverHappen(); | |
154 | } catch (e) { | |
155 | ok(e instanceof AlreadyCalledError, "swallow cancel"); | |
156 | } | |
157 | try { | |
158 | d = new Deferred(cancelled); | |
159 | d.cancel(); | |
160 | d = d.callback(1); | |
161 | neverHappen(); | |
162 | } catch (e) { | |
163 | ok(e instanceof AlreadyCalledError, "non-swallowed cancel"); | |
164 | } | |
165 | ||
166 | /* Test incorrect Deferred usage */ | |
167 | ||
168 | d = new Deferred(); | |
169 | try { | |
170 | d.callback(new Deferred()); | |
171 | neverHappen(); | |
172 | } catch (e) { | |
173 | ok (e instanceof Error, "deferred not allowed for callback"); | |
174 | } | |
175 | d = new Deferred(); | |
176 | try { | |
177 | d.errback(new Deferred()); | |
178 | neverHappen(); | |
179 | } catch (e) { | |
180 | ok (e instanceof Error, "deferred not allowed for errback"); | |
181 | } | |
182 | ||
183 | d = new Deferred(); | |
184 | (new Deferred()).addCallback(function () { return d; }).callback(1); | |
185 | try { | |
186 | d.addCallback(function () {}); | |
187 | neverHappen(); | |
188 | } catch (e) { | |
189 | ok (e instanceof Error, "chained deferred not allowed to be re-used"); | |
190 | } | |
191 | ||
192 | /* | |
193 | evalJSONRequest test | |
194 | */ | |
195 | var fakeReq = {"responseText":'[1,2,3,4,"asdf",{"a":["b", "c"]}]'}; | |
196 | var obj = [1,2,3,4,"asdf",{"a":["b", "c"]}]; | |
197 | isDeeply(obj, evalJSONRequest(fakeReq), "evalJSONRequest"); | |
198 | ||
199 | try { | |
200 | MochiKit.Async.getXMLHttpRequest(); | |
201 | ok(true, "getXMLHttpRequest"); | |
202 | } catch (e) { | |
203 | ok(false, "no love from getXMLHttpRequest"); | |
204 | } | |
205 | ||
206 | var lock = new DeferredLock(); | |
207 | var lst = []; | |
208 | var pushNumber = function (x) { | |
209 | return function (res) { lst.push(x); } | |
210 | }; | |
211 | lock.acquire().addCallback(pushNumber(1)); | |
212 | is( compare(lst, [1]), 0, "lock acquired" ); | |
213 | lock.acquire().addCallback(pushNumber(2)); | |
214 | is( compare(lst, [1]), 0, "lock waiting for release" ); | |
215 | lock.acquire().addCallback(pushNumber(3)); | |
216 | is( compare(lst, [1]), 0, "lock waiting for release" ); | |
217 | lock.release(); | |
218 | is( compare(lst, [1, 2]), 0, "lock passed on" ); | |
219 | lock.release(); | |
220 | is( compare(lst, [1, 2, 3]), 0, "lock passed on" ); | |
221 | lock.release(); | |
222 | try { | |
223 | lock.release(); | |
224 | ok( false, "over-release didn't raise" ); | |
225 | } catch (e) { | |
226 | ok( true, "over-release raised" ); | |
227 | } | |
228 | lock.acquire().addCallback(pushNumber(1)); | |
229 | is( compare(lst, [1, 2, 3, 1]), 0, "lock acquired" ); | |
230 | lock.release(); | |
231 | is( compare(lst, [1, 2, 3, 1]), 0, "lock released" ); | |
232 | ||
233 | var d = new Deferred(); | |
234 | lst = []; | |
235 | d.addCallback(operator.add, 2); | |
236 | d.addBoth(operator.add, 4); | |
237 | d.addCallback(bind(lst.push, lst)); | |
238 | d.callback(1); | |
239 | is( lst[0], 7, "auto-partial addCallback addBoth" ); | |
240 | d.addCallback(function () { throw new Error(); }); | |
241 | ebTest = function(a, b) { | |
242 | map(bind(lst.push, lst), arguments); | |
243 | }; | |
244 | d.addErrback(ebTest, "foo"); | |
245 | is( lst[1], "foo", "auto-partial errback" ); | |
246 | is( lst.length, 3, "auto-partial errback" ); | |
247 | ||
248 | /* | |
249 | Test DeferredList | |
250 | */ | |
251 | ||
252 | var callList = [new Deferred(), new Deferred(), new Deferred()]; | |
253 | callList[0].addCallback(increment); | |
254 | callList[1].addCallback(increment); | |
255 | callList[2].addCallback(increment); | |
256 | var defList = new DeferredList(callList); | |
257 | ok(defList instanceof Deferred, "DeferredList looks like a Deferred"); | |
258 | ||
259 | callList[0].callback(3); | |
260 | callList[1].callback(5); | |
261 | callList[2].callback(4); | |
262 | ||
263 | defList.addCallback(function (lst) { | |
264 | is( arrayEqual(lst, [[true, 4], [true, 6], [true, 5]]), 1, | |
265 | "deferredlist result ok" ); | |
266 | }); | |
267 | ||
268 | /* | |
269 | Test fireOnOneCallback | |
270 | */ | |
271 | ||
272 | var callList2 = [new Deferred(), new Deferred(), new Deferred()]; | |
273 | callList2[0].addCallback(increment); | |
274 | callList2[1].addCallback(increment); | |
275 | callList2[2].addCallback(increment); | |
276 | var defList2 = new DeferredList(callList2, true); | |
277 | callList2[1].callback(5); | |
278 | callList2[0].callback(3); | |
279 | callList2[2].callback(4); | |
280 | ||
281 | defList2.addCallback(function (lst) { | |
282 | is( arrayEqual(lst, [1, 6]), 1, "deferredlist fireOnOneCallback ok" ); | |
283 | }); | |
284 | ||
285 | /* | |
286 | Test fireOnOneErrback | |
287 | */ | |
288 | ||
289 | var callList3 = [new Deferred(), new Deferred(), new Deferred()]; | |
290 | callList3[0].addCallback(increment); | |
291 | callList3[1].addCallback(throwStuff); | |
292 | callList3[2].addCallback(increment); | |
293 | var defList3 = new DeferredList(callList3, false, true); | |
294 | defList3.callback = neverHappen; | |
295 | callList3[0].callback(3); | |
296 | callList3[1].callback("foo"); | |
297 | callList3[2].callback(4); | |
298 | ||
299 | defList3.addErrback(function (err) { | |
300 | is( err.message, "foo", "deferredlist fireOnOneErrback ok" ); | |
301 | }); | |
302 | ||
303 | /* | |
304 | Test consumeErrors | |
305 | */ | |
306 | ||
307 | var callList4 = [new Deferred(), new Deferred(), new Deferred()]; | |
308 | callList4[0].addCallback(increment); | |
309 | callList4[1].addCallback(throwStuff); | |
310 | callList4[2].addCallback(increment); | |
311 | var defList4 = new DeferredList(callList4, false, false, true); | |
312 | defList4.addErrback(neverHappen); | |
313 | callList4[1].addCallback(function (arg) { | |
314 | is(arg, null, "deferredlist consumeErrors ok" ); | |
315 | }); | |
316 | callList4[0].callback(3); | |
317 | callList4[1].callback("foo"); | |
318 | callList4[2].callback(4); | |
319 | ||
320 | /* | |
321 | Test gatherResults | |
322 | */ | |
323 | ||
324 | var callList5 = [new Deferred(), new Deferred(), new Deferred()]; | |
325 | callList5[0].addCallback(increment); | |
326 | callList5[1].addCallback(increment); | |
327 | callList5[2].addCallback(increment); | |
328 | var gatherRet = gatherResults(callList5); | |
329 | callList5[0].callback(3); | |
330 | callList5[1].callback(5); | |
331 | callList5[2].callback(4); | |
332 | ||
333 | gatherRet.addCallback(function (lst) { | |
334 | is( arrayEqual(lst, [4, 6, 5]), 1, | |
335 | "gatherResults result ok" ); | |
336 | }); | |
337 | ||
338 | /* | |
339 | Test maybeDeferred | |
340 | */ | |
341 | ||
342 | var maybeDef = maybeDeferred(increment, 4); | |
343 | maybeDef.addCallback(testEqCallback(5, "maybeDeferred sync ok")); | |
344 | ||
345 | var maybeDef2 = deferredIncrement(8); | |
346 | maybeDef2.addCallback(testEqCallback(9, "maybeDeferred async ok")); | |
347 | ||
348 | ok( true, "synchronous test suite finished!"); | |
349 | ||
350 | var t = (new Date().getTime()); | |
351 | SimpleTest.waitForExplicitFinish(); | |
352 | checkCallLater = function (originalTime) { | |
353 | is(originalTime, t, "argument passed in OK"); | |
354 | is(arguments.length, 1, "argument count right"); | |
355 | }; | |
356 | var lock = new DeferredLock(); | |
357 | withLock = function (msg) { | |
358 | var cb = partial.apply(null, extend(null, arguments, 1)); | |
359 | var d = lock.acquire().addCallback(cb); | |
360 | d.addErrback(ok, false, msg); | |
361 | d.addCallback(function () { | |
362 | ok(true, msg); | |
363 | lock.release(); | |
364 | }); | |
365 | return d; | |
366 | } | |
367 | withLock("callLater", function () { | |
368 | return callLater(0.05, checkCallLater, t); | |
369 | }); | |
370 | withLock("wait", function () { | |
371 | return wait(0.05, t).addCallback(checkCallLater); | |
372 | }); | |
373 | withLock("loadJSONDoc", function () { | |
374 | var d = loadJSONDoc("test_MochiKit-Async.json"); | |
375 | d.addCallback(function (doc) { | |
376 | is(doc.passed, true, "loadJSONDoc passed"); | |
377 | }); | |
378 | d.addErrback(function (doc) { | |
379 | ok(false, "loadJSONDoc failed"); | |
380 | }); | |
381 | return d; | |
382 | }); | |
383 | lock.acquire().addCallback(function () { | |
384 | ok(true, "async suite finished"); | |
385 | SimpleTest.finish(); | |
386 | }); | |
387 | ||
388 | ||
389 | } catch (err) { | |
390 | ||
391 | var s = "test suite failure!\n"; | |
392 | var o = {}; | |
393 | var k = null; | |
394 | for (k in err) { | |
395 | // ensure unique keys?! | |
396 | if (!o[k]) { | |
397 | s += k + ": " + err[k] + "\n"; | |
398 | o[k] = err[k]; | |
399 | } | |
400 | } | |
401 | ok ( false, s ); | |
402 | SimpleTest.finish(); | |
403 | ||
404 | } | |
405 | </script> | |
406 | </pre> | |
407 | </body> | |
408 | </html> |