Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/test-action.js

Issue 10233013: Crawler, second version (Closed)
Patch Set: Created April 12, 2013, 1:38 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/jsTestDriver.conf ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 ActionTest = AsyncTestCase( "ActionTest" );
2
3 /**
4 * Test that variables are defined
5 */
6 ActionTest.prototype.test__source_is_well_formed = function()
7 {
8 assertTrue( Action != null );
9 assertTrue( Action.dispatch != null );
10 };
11
12 //-------------------------------------------------------
13 // Utility
14 //-------------------------------------------------------
15
16 //-------------------------------------------------------
17 // Generic tests
18 //-------------------------------------------------------
19 /**
20 *
21 * @param {Action.Asynchronous_Action} action
22 * @param {string} state_name
23 */
24 function verify_state( action, state_name )
25 {
26 var expected = Action.State[ state_name ];
27 assertEquals( "action state is not '" + state_name + "'.", expected, action.st ate );
28 }
29
30 /**
31 * Check that an action executes its body and returns. Generic for simple, non-c ompound actions.
32 *
33 * @param {function} factory
34 * A factory function that yields an action.
35 * @param queue
36 */
37 function simple_try( factory, queue )
38 {
39 /**
40 * @type {Action.Asynchronous_Action}
41 */
42 var d = null;
43 var sequence = 0;
44
45 function trial()
46 {
47 verify_state( d, "Running" );
48 sequence += 1;
49 }
50
51 queue.call( "Go phase.", function( callbacks )
52 {
53 var monitored_trial = callbacks.add( trial );
54 d = factory( monitored_trial );
55 verify_state( d, "Ready" );
56 assertEquals( 0, sequence );
57 d.go();
58 verify_state( d, "Running" );
59 assertEquals( 0, sequence );
60 } );
61
62 queue.call( "End phase.", function()
63 {
64 verify_state( d, "Done" );
65 assertEquals( 1, sequence );
66 } );
67 }
68
69 /**
70 * Check that an action executes its body and the finisher function and returns. Generic for simple, non-compound
71 * actions. Verifying execution is done with both direct and indirect means.
72 *
73 * @param {function} factory
74 * A factory function that yields an action.
75 * @param queue
76 */
77 function simple_finally( factory, queue )
78 {
79 /**
80 * @type {Action.Asynchronous_Action}
81 */
82 var d;
83 var sequence = 0;
84
85 function trial()
86 {
87 verify_state( d, "Running" );
88 sequence += 1;
89 }
90
91 function catcher()
92 {
93 fail( "Action under test should not throw an exception nor call its catcher. " );
94 }
95
96 function finisher()
97 {
98 verify_state( d, "Done" );
99 sequence += 2;
100 }
101
102 queue.call( "Go phase.", function( callbacks )
103 {
104 var monitored_trial = callbacks.add( trial );
105 var monitored_finisher = callbacks.add( finisher );
106 d = factory( monitored_trial, monitored_finisher, catcher );
107 verify_state( d, "Ready" );
108 assertEquals( 0, sequence );
109 d.go();
110 verify_state( d, "Running" );
111 assertEquals( 0, sequence );
112 } );
113
114 queue.call( "End phase.", function()
115 {
116 verify_state( d, "Done" );
117 assertEquals( 3, sequence );
118 } );
119 }
120
121 /**
122 * Run a simple trial, one that throws an exception, with both finisher and catc her. Indirectly verify that all
123 * three run, but directly verify only the finally and catch.
124 *
125 * Generic for simple non-compound actions.
126 *
127 * @param {function} factory
128 * A factory function that yields an action.
129 * @param queue
130 */
131 function simple_catch( factory, queue )
132 {
133 /**
134 * @type {Action.Asynchronous_Action}
135 */
136 var d;
137 var sequence = 0;
138
139 function trial()
140 {
141 verify_state( d, "Running" );
142 assertEquals( 0, sequence );
143 sequence += 1;
144 throw new Error( "This error is part of the test." );
145 }
146
147 function catcher()
148 {
149 verify_state( d, "Exception" );
150 assertEquals( 1, sequence );
151 sequence += 2;
152 }
153
154 function finisher()
155 {
156 verify_state( d, "Exception" );
157 assertEquals( 3, sequence );
158 sequence += 4;
159 }
160
161 queue.call( "Go phase.", function( callbacks )
162 {
163 /* If we monitor the trial by adding to the callback list, it will report th e exception as an error, which is not
164 * what we want. We indirectly test that it runs by incrementing the sequenc e number.
165 */
166 var monitored_catch = callbacks.add( catcher );
167 var monitored_finally = callbacks.add( finisher );
168 d = factory( trial, monitored_finally, monitored_catch );
169 verify_state( d, "Ready" );
170 assertEquals( 0, sequence );
171 d.go();
172 verify_state( d, "Running" );
173 assertEquals( 0, sequence );
174 } );
175
176 queue.call( "End phase.", function()
177 {
178 verify_state( d, "Exception" );
179 assertEquals( 7, sequence );
180 } );
181 }
182
183 /**
184 * Run a simple trial, one that throws an exception, with both finisher and catc her. Indirectly verify that all
185 * three run, but directly verify only the finally and catch.
186 *
187 * Generic for simple non-compound actions.
188 *
189 * @param {function} factory
190 * A factory function that yields an action.
191 * @param queue
192 */
193 function simple_abort( factory, queue )
194 {
195 /**
196 * @type {Action.Asynchronous_Action}
197 */
198 var d;
199 var sequence = 0;
200
201 function trial()
202 {
203 fail( "Executed trial when aborted." );
204 }
205
206 function catcher()
207 {
208 verify_state( d, "Exception" );
209 assertEquals( 0, sequence );
210 sequence += 2;
211 }
212
213 function finisher()
214 {
215 verify_state( d, "Exception" );
216 assertEquals( 2, sequence );
217 sequence += 4;
218 }
219
220 queue.call( "Go phase.", function( callbacks )
221 {
222 /* If we monitor the trial by adding to the callback list, it will report th e exception as an error, which is not
223 * what we want. We indirectly test that it runs by incrementing the sequenc e number.
224 */
225 var monitored_catch = callbacks.add( catcher );
226 var monitored_finally = callbacks.add( finisher );
227 d = factory( trial, monitored_finally, monitored_catch );
228 verify_state( d, "Ready" );
229 assertEquals( 0, sequence );
230 d.go();
231 verify_state( d, "Running" );
232 assertEquals( 0, sequence );
233 d.abort();
234 verify_state( d, "Exception" );
235 assertEquals( 6, sequence );
236 } );
237 }
238
239 function simple_value( factory, queue )
240 {
241 /**
242 * @type {Action.Asynchronous_Action}
243 */
244 var d;
245
246 function trial()
247 {
248 return [ 1, "two" ];
249 }
250
251 function finisher( a, b )
252 {
253 assertEquals( 1, a );
254 assertEquals( "two", b );
255 }
256
257 queue.call( "Phase[1] Go.", function( callbacks )
258 {
259 /* If we monitor the trial by adding to the callback list, it will report th e exception as an error, which is not
260 * what we want. We indirectly test that it runs by incrementing the sequenc e number.
261 */
262 var monitored_finally = callbacks.add( finisher );
263 d = factory( trial, monitored_finally );
264 verify_state( d, "Ready" );
265 d.go();
266 verify_state( d, "Running" );
267 } );
268
269 queue.call( "Phase[2] Complete.", function()
270 {
271 verify_state( d, "Done" );
272 } );
273 }
274
275 //-------------------------------------------------------
276 // Defer
277 //-------------------------------------------------------
278 /**
279 * Factory for Defer objects
280 * @param trial
281 * @param finisher
282 * @param catcher
283 * @return {Action.Defer}
284 */
285 function defer_factory( trial, finisher, catcher )
286 {
287 return new Action.Defer( trial, finisher, catcher );
288 }
289
290 ActionTest.prototype.test_defer_try = function( queue )
291 {
292 simple_try( defer_factory, queue );
293 };
294
295 ActionTest.prototype.test_defer_finally = function( queue )
296 {
297 simple_finally( defer_factory, queue );
298 };
299
300 ActionTest.prototype.test_defer_catch = function( queue )
301 {
302 simple_catch( defer_factory, queue );
303 };
304
305 ActionTest.prototype.test_defer_abort = function( queue )
306 {
307 simple_abort( defer_factory, queue );
308 };
309
310 ActionTest.prototype.test_simple_value = function( queue )
311 {
312 simple_value( defer_factory, queue );
313 };
314
315 //-------------------------------------------------------
316 // Delay
317 //-------------------------------------------------------
318
319 /**
320 * Factory for Delay objects
321 * @param delay
322 * @param trial
323 * @param finisher
324 * @param catcher
325 * @return {Action.Delay}
326 */
327 function delay_factory( delay, trial, finisher, catcher )
328 {
329 return new Action.Delay( trial, delay, finisher, catcher );
330 }
331
332 function simple_delay_factory( trial, finisher, catcher )
333 {
334 return delay_factory( 2, trial, finisher, catcher );
335 }
336
337 ActionTest.prototype.test_delay_tries = function( queue )
338 {
339 simple_try( simple_delay_factory, queue );
340 };
341
342 ActionTest.prototype.test_delay_finally = function( queue )
343 {
344 simple_finally( simple_delay_factory, queue );
345 };
346
347 ActionTest.prototype.test_delay_catch = function( queue )
348 {
349 simple_catch( simple_delay_factory, queue );
350 };
351
352 //-------------------------------------------------------
353 // JM_Reporting implementation in Asynchronous_Action
354 //-------------------------------------------------------
355 var Asynchronous_Action__Test = AsyncTestCase( "Asynchronous_Action__Test" );
356
357 function assert_reporting_is_empty( action )
358 {
359 if ( "_end_watchers" in action )
360 {
361 // If the array exists, everything in it must be null.
362 var i;
363 for ( i = 0 ; i < action._end_watchers.length ; ++i )
364 {
365 if ( action._end_watchers[ i ] )
366 fail( "_end_watchers is still present and not empty." );
367 }
368 }
369 // If the _end_watchers array is absent, then the outbound reporting links are absent and the test passes.
370 }
371
372
373 /*
374 * Test plan: Make a simple action and join to it twice. Ensure that all mutual references are null everything
375 * completes.
376 */
377 Asynchronous_Action__Test.prototype.test_reporting__refencerences_are_absent_upo n_completion = function( queue )
378 {
379 var defer, join1, join2;
380
381 function null_function()
382 {
383 }
384
385 function reporting_has_watchers( action, n )
386 {
387 assertTrue( "_end_watchers" in action );
388 assertEquals( n, action._end_watchers.length );
389 }
390
391 function attentive_is_empty( action )
392 {
393 assertNull( "joined_action should be null.", action.joined_action );
394 }
395
396 queue.call( "Phase[1]=Go.", function( callbacks )
397 {
398 // argument[2] is the number of times to expect this function
399 var monitored_trial = callbacks.add( null_function, 1, 5000, "defer trial fu nction" );
400 var monitored_finisher = callbacks.add( null_function, 2, 5000, "join finish er function" );
401 defer = new Action.Defer( monitored_trial );
402 reporting_has_watchers( defer, 0 );
403 join1 = new Action.Join( defer, monitored_finisher );
404 join2 = new Action.Join( defer, monitored_finisher );
405 reporting_has_watchers( defer, 0 );
406 join1.go();
407 reporting_has_watchers( defer, 1 );
408 join2.go();
409 reporting_has_watchers( defer, 2 );
410 defer.go();
411 verify_state( defer, "Running" );
412 verify_state( join1, "Running" );
413 } );
414
415 queue.call( "Phase[2]=Complete.", function()
416 {
417 verify_state( defer, "Done" );
418 verify_state( join1, "Done" );
419 verify_state( join2, "Done" );
420 assert_reporting_is_empty( defer );
421 assert_reporting_is_empty( join1 );
422 assert_reporting_is_empty( join2 );
423 attentive_is_empty( join1 );
424 attentive_is_empty( join2 );
425 } );
426 };
427
428 Asynchronous_Action__Test.prototype.test_reporting__refencerences_are_absent_aft er_cancel = function( queue )
429 {
430 var defer, join;
431
432 function null_function()
433 {
434 }
435
436 function reporting_has_watchers( action, n )
437 {
438 assertTrue( "_end_watchers" in action );
439 assertEquals( n, action._end_watchers.length );
440 }
441
442 function attentive_is_empty( action )
443 {
444 assertNull( "joined_action should be null.", action.joined_action );
445 }
446
447 queue.call( "Phase[1]=Go.", function( callbacks )
448 {
449 // argument[2] is the number of times to expect this function
450 var monitored_finisher = callbacks.add( null_function, 1, 5000, "join finish er function" );
451 defer = new Action.Defer( null_function );
452 reporting_has_watchers( defer, 0 );
453 join = new Action.Join( defer, monitored_finisher );
454 reporting_has_watchers( defer, 0 );
455 join.go();
456 reporting_has_watchers( defer, 1 );
457 verify_state( defer, "Ready" );
458 verify_state( join, "Running" );
459 join.cancel();
460 verify_state( defer, "Ready" );
461 verify_state( join, "Done" );
462 assert_reporting_is_empty( defer );
463 assert_reporting_is_empty( join );
464 attentive_is_empty( join );
465 } );
466 };
467
468 //-------------------------------------------------------
469 // Join
470 //-------------------------------------------------------
471 ActionTest.prototype.test_join__throw_on_null_constructor_argument = function()
472 {
473 try
474 {
475 new Action.Join( null );
476 fail( "Join must throw an exception when passed a null constructor argument. " );
477 }
478 catch ( e )
479 {
480 // Exception is what's supposed to happen.
481 }
482 };
483
484 function join_test( variation, factory, queue )
485 /**
486 * Combined variations on a number of simple join tests. There's an ordinary act ion and a join that it depends upon.
487 * Both are invoked. The ordinary action executes first and then the join does.
488 *
489 * There are four operations {construct, go} x {ordinary, join} and some orderin g dependencies. The construction of the
490 * join must come after that of the ordinary action. Each invocation must come a fter construction. Given these
491 * constraints, there are three possible orders.
492 *
493 * @param variation
494 * @param factory
495 * @param queue
496 */
497 {
498 var sequence = 0;
499 var defer = null, join = null;
500
501 function deferred_trial()
502 {
503 // The Defer instance should run first
504 verify_state( defer, "Running" );
505 assertEquals( "deferred trial. sequence", 0, sequence );
506 sequence += 1;
507 }
508
509 function join_catcher()
510 {
511 fail( "Joined catcher should not be called." );
512 }
513
514 function join_finisher( x )
515 {
516 assertEquals( "joined finisher. number of arguments", 1, arguments.length );
517 assertEquals( "joined finisher. first argument", "ABC", x );
518 // The Join instance should run second.
519 verify_state( defer, "Done" );
520 verify_state( join, "Done" );
521 assertEquals( "joined finisher. sequence", 1, sequence );
522 sequence += 2;
523 }
524
525 /*
526 * The split finisher supports the case where we need to construct a join in o ne phase but launch it in another.
527 * Because of a monitored function must complete in the same phase in which it set to be monitored, we need a static
528 * function that we can use to initialize and a variable we can initialize in a later phase.
529 */
530 var split_finisher_f;
531
532 function split_finisher()
533 {
534 if ( !split_finisher_f )
535 throw new Error( "split_finisher_f is not initialized" );
536 split_finisher_f.apply( this, arguments );
537 }
538
539 function monitored_join_finisher( callbacks )
540 {
541 return callbacks.add( join_finisher, null, 2000, "join finisher" );
542 }
543
544 function make_join( finisher )
545 {
546 join = factory( defer, finisher, join_catcher );
547 verify_state( join, "Ready" );
548 }
549
550 function join_go()
551 {
552 join.go( "ABC" );
553 }
554
555 queue.call( "Phase[1]=Go.", function( callbacks )
556 {
557 /*
558 * Construction of the Defer instance always has to come first.
559 */
560 defer = new Action.Defer( callbacks.add( deferred_trial, null, 2000, "defer_ trial" ) );
561 verify_state( defer, "Ready" );
562 switch ( variation )
563 {
564 case "existing ready":
565 /*
566 * Invoke the join before the defer has been invoked. This tests joining to a ready action.
567 */
568 make_join( monitored_join_finisher( callbacks ) );
569 join_go();
570 defer.go();
571 verify_state( defer, "Running" );
572 verify_state( join, "Running" );
573 break;
574 case "existing running":
575 /*
576 * Invoke the join after the defer has been invoked. This tests joining to a running action.
577 */
578 make_join( monitored_join_finisher( callbacks ) );
579 defer.go();
580 join_go();
581 /*
582 * The defer is running, but it hasn't completed yet, so the join hasn't completed yet. Contrast this with
583 * the split version, where the defer action has already completed when we invoke the join.
584 */
585 verify_state( defer, "Running" );
586 verify_state( join, "Running" );
587 break;
588 case "existing running split":
589 /*
590 * Invoke the defer after the join is invoked, but invoke the join later . This test ensures that the join
591 * does not complete prematurely.
592 */
593 make_join( split_finisher );
594 defer.go();
595 verify_state( defer, "Running" );
596 verify_state( join, "Ready" );
597 break;
598 case "new running":
599 /*
600 * Construct the join after defer has already been invoked.
601 */
602 defer.go();
603 make_join( monitored_join_finisher( callbacks ) );
604 join_go();
605 verify_state( defer, "Running" );
606 verify_state( join, "Running" );
607 break;
608 default:
609 throw new Error( "unknown variation" );
610 }
611 } );
612
613 queue.call( "Phase[2]=Intermediate.", function( callbacks )
614 {
615 switch ( variation )
616 {
617 case "existing running split":
618 split_finisher_f = monitored_join_finisher( callbacks );
619 /*
620 * The join should not yet have run at this point.
621 */
622 verify_state( defer, "Done" );
623 verify_state( join, "Ready" );
624 /*
625 * We invoke the join on a completed action. As a result, the join will complete immediately.
626 */
627 join_go();
628 verify_state( defer, "Done" );
629 verify_state( join, "Done" );
630 break;
631 default:
632 /*
633 * We're already verified the variation in the first phase. Some variati ons have no intermediate phase.
634 */
635 break;
636 }
637 } );
638
639 queue.call( "Phase[3]=End.", function()
640 {
641 verify_state( defer, "Done" );
642 verify_state( join, "Done" );
643 assertEquals( 3, sequence );
644 } );
645 }
646
647 //-------------------------------------------------------
648 // Join
649 //-------------------------------------------------------
650 /**
651 * @param action
652 * @param [finisher]
653 * @param [catcher]
654 * @return {Action.Join}
655 */
656 function join_factory( action, finisher, catcher )
657 {
658 return new Action.Join( action, finisher, catcher );
659 }
660
661 ActionTest__Join = AsyncTestCase( "Join" );
662
663 ActionTest__Join.prototype.test_join__existing_join_to_new_defer_instance = func tion( queue )
664 {
665 join_test( "existing ready", join_factory, queue );
666 };
667
668 ActionTest__Join.prototype.test_join__existing_join_to_running_defer_instance = function( queue )
669 {
670 join_test( "existing running", join_factory, queue );
671 };
672
673 ActionTest__Join.prototype.test_join__existing_join_to_running_defer_instance__s plit = function( queue )
674 {
675 join_test( "existing running split", join_factory, queue );
676 };
677
678 ActionTest__Join.prototype.test_join__new_join_to_running_defer_instance = funct ion( queue )
679 {
680 join_test( "new running", join_factory, queue )
681 };
682
683 //-------------------------------------------------------
684 // ActionTest__Join_Timeout
685 //-------------------------------------------------------
686 /**
687 * Join_Timeout factory set at 15 seconds, which should be enough longer than ca llback limit, set to 2 seconds, to
688 * avoid false negatives.
689 *
690 * @param action
691 * @param [finisher]
692 * @param [catcher]
693 * @return {Action.Join_Timeout}
694 */
695 function join_timeout_factory( action, finisher, catcher )
696 {
697 return new Action.Join_Timeout( action, 15000, finisher, catcher );
698 }
699
700 ActionTest__Join_Timeout = AsyncTestCase( "Join_Timeout" );
701
702 ActionTest__Join_Timeout.prototype.test_join_timeout__existing_join_to_new_defer _instance = function( queue )
703 {
704 join_test( "existing ready", join_timeout_factory, queue );
705 };
706
707 ActionTest__Join_Timeout.prototype.test_join_timeout__existing_join_to_running_d efer_instance = function( queue )
708 {
709 join_test( "existing running", join_timeout_factory, queue );
710 };
711
712 ActionTest__Join_Timeout.prototype.test_join_timeout__existing_join_to_running_d efer_instance__split = function( queue )
713 {
714 join_test( "existing running split", join_timeout_factory, queue );
715 };
716
717 ActionTest__Join_Timeout.prototype.test_join_timeout__new_join_to_running_defer_ instance = function( queue )
718 {
719 join_test( "new running", join_timeout_factory, queue )
720 };
721
722 ActionTest__Join_Timeout.prototype.test_join_timeout__simple_timeout = function( queue )
723 {
724 var sequence = 0;
725
726 function defer_trial()
727 {
728 fail( "The trial on the defer object should not be called." );
729 }
730
731 function join_catch()
732 {
733 assertEquals( 0, sequence );
734 sequence += 1;
735 verify_state( defer, "Ready" );
736 verify_state( join, "Exception" );
737 assertTrue( "Join should be exceptional.", !join.completed_well );
738 }
739
740 function join_finally()
741 {
742 }
743
744 /*
745 * Construct the defer object outside the test queue because it does not gener ate a callback in this case.
746 */
747 var defer = new Action.Defer( defer_trial );
748 verify_state( defer, "Ready" );
749 var join;
750 queue.call( "Phase[1]=Go.", function( callbacks )
751 {
752 /*
753 * Timeout is set to a very short time.
754 */
755 var monitored_join_catch = callbacks.add( join_catch, null, 5000, "join catc h" );
756 join = new Action.Join_Timeout( defer, 1, join_finally, monitored_join_catch );
757 join.go();
758 } );
759 /*
760 * No need to launch the Defer action. If the timeout doesn't trigger the catc her, the test fails.
761 */
762 };
763
OLDNEW
« no previous file with comments | « test/jsTestDriver.conf ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld