| OLD | NEW | 
|---|
| (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 | 
| OLD | NEW | 
|---|