ruote 2.1.10 → 2.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. data/CHANGELOG.txt +51 -1
  2. data/CREDITS.txt +9 -0
  3. data/README.rdoc +13 -0
  4. data/Rakefile +50 -21
  5. data/TODO.txt +42 -4
  6. data/examples/pong.rb +37 -0
  7. data/lib/ruote/context.rb +19 -9
  8. data/lib/ruote/engine/process_error.rb +10 -0
  9. data/lib/ruote/engine/process_status.rb +140 -41
  10. data/lib/ruote/engine.rb +394 -27
  11. data/lib/ruote/exp/command.rb +2 -0
  12. data/lib/ruote/exp/fe_concurrence.rb +8 -0
  13. data/lib/ruote/exp/fe_concurrent_iterator.rb +3 -0
  14. data/lib/ruote/exp/fe_cursor.rb +48 -4
  15. data/lib/ruote/exp/fe_iterator.rb +40 -0
  16. data/lib/ruote/exp/fe_listen.rb +3 -3
  17. data/lib/ruote/exp/fe_participant.rb +30 -12
  18. data/lib/ruote/exp/fe_ref.rb +126 -0
  19. data/lib/ruote/exp/fe_subprocess.rb +20 -1
  20. data/lib/ruote/exp/fe_wait.rb +4 -1
  21. data/lib/ruote/exp/fe_when.rb +7 -10
  22. data/lib/ruote/exp/flowexpression.rb +23 -12
  23. data/lib/ruote/exp/ro_attributes.rb +5 -8
  24. data/lib/ruote/exp/ro_variables.rb +4 -2
  25. data/lib/ruote/fei.rb +2 -0
  26. data/lib/ruote/id/wfid_generator.rb +1 -1
  27. data/lib/ruote/log/pretty.rb +137 -0
  28. data/lib/ruote/log/storage_history.rb +1 -1
  29. data/lib/ruote/log/test_logger.rb +51 -126
  30. data/lib/ruote/log/wait_logger.rb +8 -13
  31. data/lib/ruote/parser/ruby_dsl.rb +4 -4
  32. data/lib/ruote/parser.rb +2 -2
  33. data/lib/ruote/part/block_participant.rb +1 -1
  34. data/lib/ruote/part/engine_participant.rb +1 -1
  35. data/lib/ruote/part/storage_participant.rb +27 -28
  36. data/lib/ruote/part/template.rb +8 -3
  37. data/lib/ruote/receiver/base.rb +24 -6
  38. data/lib/ruote/storage/base.rb +76 -11
  39. data/lib/ruote/storage/fs_storage.rb +10 -0
  40. data/lib/ruote/storage/hash_storage.rb +19 -8
  41. data/lib/ruote/{part → svc}/dispatch_pool.rb +3 -2
  42. data/lib/ruote/svc/dollar_sub.rb +265 -0
  43. data/lib/ruote/{error_handler.rb → svc/error_handler.rb} +6 -1
  44. data/lib/ruote/{exp → svc}/expression_map.rb +31 -37
  45. data/lib/ruote/{part → svc}/participant_list.rb +165 -25
  46. data/lib/ruote/{evt → svc}/tracker.rb +0 -0
  47. data/lib/ruote/{util → svc}/treechecker.rb +0 -0
  48. data/lib/ruote/util/look.rb +4 -1
  49. data/lib/ruote/util/ometa.rb +21 -5
  50. data/lib/ruote/{subprocess.rb → util/subprocess.rb} +0 -0
  51. data/lib/ruote/version.rb +1 -1
  52. data/lib/ruote/worker.rb +29 -69
  53. data/lib/ruote/workitem.rb +28 -1
  54. data/ruote.gemspec +26 -22
  55. data/test/functional/base.rb +3 -0
  56. data/test/functional/concurrent_base.rb +1 -0
  57. data/test/functional/crunner.sh +1 -1
  58. data/test/functional/ct_0_concurrence.rb +6 -0
  59. data/test/functional/ct_1_iterator.rb +3 -0
  60. data/test/functional/ct_2_cancel.rb +5 -0
  61. data/test/functional/eft_13_iterator.rb +39 -4
  62. data/test/functional/eft_14_cursor.rb +39 -0
  63. data/test/functional/eft_30_ref.rb +140 -0
  64. data/test/functional/eft_3_participant.rb +25 -23
  65. data/test/functional/ft_10_dollar.rb +17 -1
  66. data/test/functional/ft_14_re_apply.rb +76 -0
  67. data/test/functional/ft_1_process_status.rb +170 -29
  68. data/test/functional/ft_20_storage_participant.rb +14 -0
  69. data/test/functional/ft_24_block_participants.rb +1 -1
  70. data/test/functional/ft_26_participant_timeout.rb +93 -0
  71. data/test/functional/ft_2_errors.rb +24 -17
  72. data/test/functional/ft_30_smtp_participant.rb +7 -2
  73. data/test/functional/ft_38_participant_more.rb +15 -0
  74. data/test/functional/ft_39_wait_for.rb +34 -1
  75. data/test/functional/ft_3_participant_registration.rb +270 -2
  76. data/test/functional/ft_40_wait_logger.rb +61 -0
  77. data/test/functional/ft_42_storage_copy.rb +4 -0
  78. data/test/functional/{ft_40_participant_on_reply.rb → ft_43_participant_on_reply.rb} +17 -0
  79. data/test/functional/ft_44_var_participant.rb +35 -0
  80. data/test/functional/ft_45_participant_accept.rb +64 -0
  81. data/test/functional/ft_46_launch_single.rb +49 -0
  82. data/test/functional/ft_5_on_error.rb +39 -1
  83. data/test/functional/storage_helper.rb +7 -1
  84. data/test/test_helper.rb +1 -1
  85. data/test/unit/storage.rb +105 -32
  86. data/test/unit/ut_0_ruby_parser.rb +31 -1
  87. data/test/unit/ut_16_parser.rb +20 -0
  88. data/test/unit/ut_19_part_template.rb +11 -1
  89. data/test/unit/ut_20_composite_storage.rb +1 -1
  90. data/test/unit/ut_4_expmap.rb +1 -1
  91. data/test/unit/ut_6_condition.rb +2 -2
  92. metadata +112 -74
  93. data/lib/ruote/exp/raw.rb +0 -44
  94. data/lib/ruote/util/dollar.rb +0 -193
@@ -8,6 +8,7 @@
8
8
  require File.join(File.dirname(__FILE__), 'base')
9
9
 
10
10
  require 'ruote/part/hash_participant'
11
+ require 'ruote/part/storage_participant'
11
12
 
12
13
 
13
14
  class FtReApplyTest < Test::Unit::TestCase
@@ -219,5 +220,80 @@ class FtReApplyTest < Test::Unit::TestCase
219
220
 
220
221
  assert_equal "re_applied\ndone.", @tracer.to_s
221
222
  end
223
+
224
+ def test_new_tree_and_process_status_current_tree
225
+
226
+ @engine.register_participant '.+', Ruote::StorageParticipant
227
+
228
+ wfid = @engine.launch(Ruote.define { alpha })
229
+
230
+ @engine.wait_for(:alpha)
231
+
232
+ assert_equal(
233
+ [ 'define', {}, [ [ 'participant', { 'ref' => 'alpha' }, [] ] ] ],
234
+ @engine.process(wfid).current_tree)
235
+
236
+ fei = @engine.storage_participant.first.fei
237
+
238
+ @engine.re_apply(fei, :tree => [ 'bravo', {}, [] ])
239
+
240
+ @engine.wait_for(:bravo)
241
+
242
+ assert_equal(
243
+ 'bravo',
244
+ @engine.storage_participant.first.participant_name)
245
+
246
+ assert_equal(
247
+ [ 'participant', { 'ref' => 'bravo', '_triggered' => 'on_re_apply' }, [] ],
248
+ @engine.process(wfid).expressions.last.tree)
249
+
250
+ assert_equal(
251
+ [ 'define', {}, [ [ 'participant', { 'ref' => 'bravo', '_triggered' => 'on_re_apply' }, [] ] ] ],
252
+ @engine.process(wfid).current_tree)
253
+ end
254
+
255
+ # Issue reported by Brett Anthoine
256
+ #
257
+ def test_re_apply_root
258
+
259
+ @engine.register_participant '.+', Ruote::StorageParticipant
260
+
261
+ wfid = @engine.launch(Ruote.define { alpha })
262
+
263
+ @engine.wait_for(:alpha)
264
+ at0 = @engine.storage_participant.first.dispatched_at
265
+
266
+ root = @engine.process(wfid).root_expression
267
+ @engine.re_apply(root.fei)
268
+
269
+ @engine.wait_for(:alpha)
270
+ at1 = @engine.storage_participant.first.dispatched_at
271
+
272
+ assert at1 > at0
273
+ end
274
+
275
+ def test_re_apply_define
276
+
277
+ @engine.register_participant '.+', Ruote::StorageParticipant
278
+
279
+ wfid = @engine.launch(Ruote.define do
280
+ sub0
281
+ define 'sub0' do
282
+ alpha
283
+ end
284
+ end)
285
+
286
+ @engine.wait_for(:alpha)
287
+ at0 = @engine.storage_participant.first.dispatched_at
288
+
289
+ exp = @engine.process(wfid).expressions[1]
290
+
291
+ @engine.re_apply(exp.fei)
292
+
293
+ @engine.wait_for(:alpha)
294
+ at1 = @engine.storage_participant.first.dispatched_at
295
+
296
+ assert at1 > at0
297
+ end
222
298
  end
223
299
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  require File.join(File.dirname(__FILE__), 'base')
9
9
 
10
- require 'ruote/part/hash_participant'
10
+ require 'ruote/participant'
11
11
 
12
12
 
13
13
  class FtProcessStatusTest < Test::Unit::TestCase
@@ -36,29 +36,6 @@ class FtProcessStatusTest < Test::Unit::TestCase
36
36
  assert_equal(
37
37
  {"my process"=>["0", ["define", {"name"=>"my process"}, [["participant", {"ref"=>"alpha"}, []]]]]},
38
38
  ps.variables)
39
-
40
- # checking process_status.to_h
41
-
42
- h = ps.to_h
43
- #p h
44
-
45
- assert_equal wfid, h['wfid']
46
- assert_equal 2, h['expressions'].size
47
- assert_equal 'my process', h['definition_name']
48
-
49
- assert_equal Time, Time.parse(h['launched_time']).class
50
-
51
- assert_equal(
52
- ["define", {"name"=>"my process"}, [["participant", {"ref"=>"alpha"}, []]]],
53
- h['original_tree'])
54
-
55
- assert_equal(
56
- ["define", {"name"=>"my process"}, [["participant", {"ref"=>"alpha"}, []]]],
57
- h['current_tree'])
58
-
59
- assert_equal(
60
- {"my process"=>["0", ["define", {"name"=>"my process"}, [["participant", {"ref"=>"alpha"}, []]]]]},
61
- h['variables'])
62
39
  end
63
40
 
64
41
  def test_variables
@@ -90,19 +67,21 @@ class FtProcessStatusTest < Test::Unit::TestCase
90
67
  nada
91
68
  end
92
69
 
93
- wfid = @engine.launch( pdef )
94
- wait_for( wfid )
70
+ wfid = @engine.launch(pdef)
71
+ wait_for(wfid)
95
72
 
96
73
  errs = @engine.errors
97
74
 
98
75
  assert_equal 1, errs.size
99
76
 
100
- assert_equal wfid, errs.first['fei']['wfid']
77
+ assert_equal wfid, errs.first.wfid
101
78
 
102
- err = @engine.errors( wfid )
79
+ err = @engine.errors(wfid)
103
80
 
104
81
  assert_equal 1, err.size
105
- assert_equal wfid, err.first['fei']['wfid']
82
+ assert_equal wfid, err.first.wfid
83
+
84
+ assert_equal 1, @engine.errors(:count => true)
106
85
  end
107
86
 
108
87
  def test_tree
@@ -496,5 +475,167 @@ digraph "process wfid wfid" {
496
475
  }.strip,
497
476
  dot)
498
477
  end
478
+
479
+ def test_last_active
480
+
481
+ pdef = Ruote.define do
482
+ alpha
483
+ bravo
484
+ end
485
+
486
+ @engine.register_participant '.+', Ruote::StorageParticipant
487
+
488
+ wfid = @engine.launch(pdef)
489
+
490
+ @engine.wait_for(:alpha)
491
+
492
+ t0 = Time.parse(@engine.process(wfid).last_active)
493
+
494
+ sp = @engine.storage_participant
495
+ sp.reply(sp.first)
496
+
497
+ @engine.wait_for(:bravo)
498
+
499
+ t1 = Time.parse(@engine.process(wfid).last_active)
500
+
501
+ assert t1 > t0
502
+ end
503
+
504
+ def test_position
505
+
506
+ pdef = Ruote.define do
507
+ alpha :task => 'clean car'
508
+ end
509
+
510
+ @engine.register_participant '.+', Ruote::StorageParticipant
511
+
512
+ wfid = @engine.launch(pdef)
513
+ @engine.wait_for(:alpha)
514
+
515
+ assert_equal(
516
+ [ [ "0_0!!#{wfid}", 'alpha', { 'task' => 'clean car' } ] ],
517
+ @engine.process(wfid).position)
518
+
519
+ # #position leverages #workitems
520
+
521
+ assert_equal(
522
+ [ 'alpha' ],
523
+ @engine.process(wfid).workitems.collect { |wi| wi.participant_name })
524
+ end
525
+
526
+ def test_ps_with_stored_workitems
527
+
528
+ @engine.register_participant '.+', Ruote::StorageParticipant
529
+
530
+ wfid = @engine.launch(Ruote.define { alpha })
531
+ @engine.wait_for(:alpha)
532
+
533
+ ps = @engine.process(wfid)
534
+
535
+ assert_equal 1, ps.stored_workitems.size
536
+ assert_equal Ruote::Workitem, ps.stored_workitems.first.class
537
+ end
538
+
539
+ def test_ps_without_stored_workitems
540
+
541
+ @engine.register_participant '.+', Ruote::NullParticipant
542
+
543
+ wfid = @engine.launch(Ruote.define { alpha })
544
+ @engine.wait_for(:alpha)
545
+
546
+ ps = @engine.process(wfid)
547
+
548
+ assert_equal 0, ps.stored_workitems.size
549
+ end
550
+
551
+ def test_schedules
552
+
553
+ @engine.register_participant '.+', Ruote::NullParticipant
554
+
555
+ wfid = @engine.launch(Ruote.define { alpha :timeout => '2d' })
556
+ @engine.wait_for(:alpha)
557
+
558
+ assert_equal 1, @engine.schedules.size
559
+ assert_equal 1, @engine.schedules(:count => true)
560
+ end
561
+
562
+ def test_ps_and_schedules
563
+
564
+ @engine.register_participant '.+', Ruote::NullParticipant
565
+
566
+ #noisy
567
+
568
+ wfid = @engine.launch(Ruote.define { alpha :timeout => '2d' })
569
+ @engine.wait_for(:alpha)
570
+
571
+ ps = @engine.process(wfid)
572
+
573
+ assert_equal 1, ps.schedules.size
574
+ assert_equal "0_0!!#{wfid}", ps.schedules.first['target'].sid
575
+ end
576
+
577
+ def test_ps_pagination
578
+
579
+ n = 7
580
+
581
+ @engine.register_participant '.+', Ruote::StorageParticipant
582
+
583
+ wfids = (1..n).collect { |i|
584
+ @engine.launch(Ruote.define { alpha })
585
+ }.sort
586
+
587
+ while @engine.storage_participant.size < n; sleep 0.140; end
588
+
589
+ assert_equal wfids, @engine.process_wfids
590
+
591
+ assert_equal(
592
+ wfids,
593
+ @engine.processes.collect { |ps| ps.wfid })
594
+
595
+ assert_equal(
596
+ wfids[0, 3],
597
+ @engine.processes(:limit => 3).collect { |ps| ps.wfid })
598
+
599
+ assert_equal(
600
+ wfids[3, 3],
601
+ @engine.processes(:skip => 3, :limit => 3).collect { |ps| ps.wfid })
602
+
603
+ #puts "==="
604
+ #wfids.each { |wfid| puts wfid }
605
+ #puts "---"
606
+ #@engine.processes(:limit => 3, :descending => false).collect { |ps| ps.wfid }.each { |wfid| puts wfid }
607
+ #puts "---"
608
+ #@engine.processes(:limit => 3, :descending => true).collect { |ps| ps.wfid }.each { |wfid| puts wfid }
609
+
610
+ assert_equal(
611
+ wfids.reverse[0, 3],
612
+ @engine.processes(
613
+ :limit => 3, :descending => true
614
+ ).collect { |ps| ps.wfid })
615
+
616
+ assert_equal(
617
+ n,
618
+ @engine.processes(:count => true))
619
+ end
620
+
621
+ # Issue identified by David Goodlad :
622
+ #
623
+ # http://gist.github.com/600451
624
+ #
625
+ def test_ps_and_schedules
626
+
627
+ pdef = Ruote.define do
628
+ concurrence do
629
+ wait '4h'
630
+ wait '2h'
631
+ end
632
+ end
633
+
634
+ @engine.launch(pdef)
635
+
636
+ sleep 0.400
637
+
638
+ assert_equal 1, @engine.processes.size
639
+ end
499
640
  end
500
641
 
@@ -180,6 +180,8 @@ class FtStorageParticipantTest < Test::Unit::TestCase
180
180
  assert_equal 2, @part.query('place' => 'heiankyou', :limit => 2).size
181
181
  assert_equal 4, @part.query('place' => 'heiankyou', :limit => 20).size
182
182
 
183
+ assert_equal 4, @part.query(:count => true)
184
+
183
185
  page0 =
184
186
  @part.query('place' => 'heiankyou', :limit => 2).collect { |wi|
185
187
  "#{wi.fei.wfid}-#{wi.participant_name}" }
@@ -309,5 +311,17 @@ class FtStorageParticipantTest < Test::Unit::TestCase
309
311
  assert_equal wi, sp[wi.fei.to_h]
310
312
  assert_equal wi, sp[wi.fei.to_storage_id]
311
313
  end
314
+
315
+ def test_engine_storage_participant
316
+
317
+ @engine.register_participant 'step_.*', Ruote::StorageParticipant
318
+
319
+ wfid = @engine.launch(Ruote.process_definition { step_one })
320
+
321
+ wait_for(:step_one)
322
+
323
+ assert_equal 1, @engine.storage_participant.size
324
+ assert_equal 'step_one', @engine.storage_participant.first.participant_name
325
+ end
312
326
  end
313
327
 
@@ -62,7 +62,7 @@ class FtBlockParticipantTest < Test::Unit::TestCase
62
62
  def test_non_jsonfiable_result
63
63
 
64
64
  return if Ruote::WIN
65
- # defective 'json' lib on windows render this test useless
65
+ # defective 'json' lib on windows renders this test useless
66
66
 
67
67
  t = Time.now
68
68
 
@@ -45,5 +45,98 @@ class FtParticipantTimeoutTest < Test::Unit::TestCase
45
45
 
46
46
  assert_not_nil bravo.first.fields['__timed_out__']
47
47
  end
48
+
49
+ class MyParticipant
50
+ include Ruote::LocalParticipant
51
+ def consume (workitem)
52
+ # do nothing
53
+ end
54
+ def cancel (fei, flavour)
55
+ # do nothing
56
+ end
57
+ def timeout
58
+ '1s'
59
+ end
60
+ def do_not_thread
61
+ true
62
+ end
63
+ end
64
+
65
+ def test_participant_class_defined_timeout
66
+
67
+ pdef = Ruote.define do
68
+ alpha
69
+ echo 'done.'
70
+ end
71
+
72
+ @engine.register_participant :alpha, MyParticipant
73
+
74
+ #noisy
75
+
76
+ wfid = @engine.launch(pdef)
77
+
78
+ @engine.wait_for(wfid)
79
+
80
+ assert_equal 'done.', @tracer.to_s
81
+ assert_equal 2, logger.log.select { |e| e['flavour'] == 'timeout' }.size
82
+ end
83
+
84
+ def test_pdef_overriden_timeout
85
+
86
+ # process definition cancels timeout given by participant
87
+
88
+ pdef = Ruote.define do
89
+ alpha :timeout => ''
90
+ echo 'done.'
91
+ end
92
+
93
+ @engine.register_participant :alpha, MyParticipant
94
+
95
+ wfid = @engine.launch(pdef)
96
+
97
+ @engine.wait_for(:alpha)
98
+
99
+ sleep 0.350
100
+
101
+ assert_equal 0, @engine.storage.get_many('schedules').size
102
+ assert_equal '', @tracer.to_s
103
+ end
104
+
105
+ class MyOtherParticipant
106
+ include Ruote::LocalParticipant
107
+ def initialize (opts)
108
+ @opts = opts
109
+ end
110
+ def consume (workitem)
111
+ # do nothing
112
+ end
113
+ def cancel (fei, flavour)
114
+ # do nothing
115
+ end
116
+ def timeout
117
+ @opts['timeout']
118
+ end
119
+ end
120
+
121
+ def test_participant_option_defined_timeout
122
+
123
+ pdef = Ruote.define do
124
+ alpha
125
+ bravo
126
+ echo 'done.'
127
+ end
128
+
129
+ @engine.register_participant :alpha, MyOtherParticipant, 'timeout' => '1s'
130
+ @engine.register_participant :bravo, MyOtherParticipant
131
+
132
+ #noisy
133
+
134
+ wfid = @engine.launch(pdef)
135
+
136
+ @engine.wait_for(:bravo)
137
+
138
+ assert_equal 0, @engine.storage.get_many('schedules').size
139
+ # no timeout for participant :bravo
140
+ end
48
141
  end
49
142
 
@@ -19,8 +19,6 @@ class FtErrorsTest < Test::Unit::TestCase
19
19
  nada
20
20
  end
21
21
 
22
- #noisy
23
-
24
22
  wfid = @engine.launch(pdef)
25
23
  wait_for(wfid)
26
24
 
@@ -49,7 +47,7 @@ class FtErrorsTest < Test::Unit::TestCase
49
47
 
50
48
  ps = @engine.process(wfid)
51
49
 
52
- exp = ps.expressions.find { |fe| fe.class == Ruote::Exp::RawExpression }
50
+ exp = ps.expressions.find { |fe| fe.class == Ruote::Exp::RefExpression }
53
51
 
54
52
  assert_not_nil exp
55
53
 
@@ -115,7 +113,7 @@ class FtErrorsTest < Test::Unit::TestCase
115
113
  ps = @engine.process(wfid)
116
114
 
117
115
  err = ps.errors.first
118
- assert_equal [ 'nada', {}, [] ], err.tree
116
+ assert_equal [ 'nada', { 'ref' => 'nada' }, [] ], err.tree
119
117
 
120
118
  err.tree = [ 'alpha', {}, [] ]
121
119
  @engine.replay_at_error(err)
@@ -339,26 +337,35 @@ class FtErrorsTest < Test::Unit::TestCase
339
337
  assert_nil @engine.process(wfid)
340
338
  end
341
339
 
342
- def test_ps_to_h
340
+ #def test_ps_to_h
341
+ # pdef = Ruote.process_definition do
342
+ # error 'nada'
343
+ # end
344
+ # #noisy
345
+ # wfid = @engine.launch(pdef)
346
+ # wait_for(wfid)
347
+ # ps = @engine.process(wfid)
348
+ # es = ps.to_h['errors']
349
+ # e = es.first
350
+ # assert_equal 1, es.size
351
+ # assert_equal 'reply', e['msg']['action']
352
+ # assert_equal wfid, e['msg']['fei']['wfid']
353
+ # assert_equal 8, e.size
354
+ #end
355
+
356
+ def test_error_intercepted
343
357
 
344
358
  pdef = Ruote.process_definition do
345
- error 'nada'
359
+ nada
346
360
  end
347
361
 
348
- #noisy
349
-
350
362
  wfid = @engine.launch(pdef)
351
- wait_for(wfid)
352
-
353
- ps = @engine.process(wfid)
354
363
 
355
- es = ps.to_h['errors']
356
- e = es.first
364
+ r = @engine.wait_for(wfid)
357
365
 
358
- assert_equal 1, es.size
359
- assert_equal 'reply', e['msg']['action']
360
- assert_equal wfid, e['msg']['fei']['wfid']
361
- assert_equal 8, e.size
366
+ assert_equal 'RuntimeError', r['error_class']
367
+ assert_equal "unknown participant or subprocess 'nada'", r['error_message']
368
+ assert_equal Array, r['error_backtrace'].class
362
369
  end
363
370
  end
364
371
 
@@ -80,7 +80,9 @@ class NftSmtpParticipantTest < Test::Unit::TestCase
80
80
  end
81
81
  end
82
82
 
83
- trapfile = Ruote::WIN ? 'ruote_mailtrap.txt' : '/tmp/ruote_mailtrap.txt'
83
+ trapfile = "ruote_mailtrap_#{$$}_#{Time.now.to_f}.txt"
84
+
85
+ trapfile = Ruote::WIN ? trapfile : "/tmp/#{trapfile}"
84
86
  FileUtils.rm_f(trapfile)
85
87
 
86
88
  t = Thread.new do
@@ -108,7 +110,10 @@ class NftSmtpParticipantTest < Test::Unit::TestCase
108
110
  #sleep 0.450
109
111
  wait_for(wfid)
110
112
 
111
- assert_match(/want cat food/, File.read(trapfile))
113
+ trapped = File.read(trapfile)
114
+ FileUtils.rm_f(trapfile)
115
+
116
+ assert_match /want cat food/, trapped
112
117
  assert_nil @engine.process(wfid)
113
118
 
114
119
  t.kill
@@ -30,6 +30,8 @@ class FtParticipantMoreTest < Test::Unit::TestCase
30
30
  end
31
31
  end
32
32
 
33
+ # Reject and re_dispatch are aliases.
34
+ #
33
35
  def test_participant_reject
34
36
 
35
37
  pdef = Ruote.process_definition do
@@ -59,6 +61,8 @@ class FtParticipantMoreTest < Test::Unit::TestCase
59
61
  end
60
62
  end
61
63
 
64
+ # Reject and re_dispatch are aliases.
65
+ #
62
66
  def test_participant_re_dispatch
63
67
 
64
68
  pdef = Ruote.process_definition do
@@ -92,6 +96,11 @@ class FtParticipantMoreTest < Test::Unit::TestCase
92
96
  end
93
97
  end
94
98
 
99
+ # Reject and re_dispatch are aliases.
100
+ #
101
+ # re_dispatch with an :in or an :at parameter makes sure the dispatch is
102
+ # performed once more, but a bit later (:in / :at timepoint).
103
+ #
95
104
  def test_participant_re_dispatch_later
96
105
 
97
106
  pdef = Ruote.process_definition do
@@ -112,6 +121,9 @@ class FtParticipantMoreTest < Test::Unit::TestCase
112
121
  assert t < 2.0, "took more than 1.99 second"
113
122
  end
114
123
 
124
+ # Making sure that when a process gets cancelled, its 'later' re-dispatches
125
+ # are cancelled as well.
126
+ #
115
127
  def test_participant_re_dispatch_later_cancel
116
128
 
117
129
  pdef = Ruote.process_definition do
@@ -146,6 +158,9 @@ class FtParticipantMoreTest < Test::Unit::TestCase
146
158
  end
147
159
  end
148
160
 
161
+ # Stashing lets a stateless participant 'stash' state via put() and get()
162
+ # into the engine.
163
+ #
149
164
  def test_stash
150
165
 
151
166
  BLACKBOARD.clear
@@ -10,7 +10,7 @@ require File.join(File.dirname(__FILE__), 'base')
10
10
  require 'ruote/part/storage_participant'
11
11
 
12
12
 
13
- class FtEngineTest < Test::Unit::TestCase
13
+ class FtWaitForTest < Test::Unit::TestCase
14
14
  include FunctionalBase
15
15
 
16
16
  def test_workitem
@@ -96,5 +96,38 @@ class FtEngineTest < Test::Unit::TestCase
96
96
 
97
97
  assert_equal wfids.sort, @engine.processes.collect { |ps| ps.wfid }.sort
98
98
  end
99
+
100
+ def test_wait_for_multithreaded
101
+
102
+ pdef = Ruote.process_definition { alpha }
103
+
104
+ sp = @engine.register_participant :alpha, Ruote::StorageParticipant
105
+
106
+ #noisy
107
+
108
+ wfid = @engine.launch(pdef)
109
+
110
+ seen = []
111
+
112
+ Thread.new do
113
+ @engine.wait_for(wfid)
114
+ seen << 'this'
115
+ end
116
+ Thread.new do
117
+ @engine.wait_for(wfid)
118
+ seen << 'that'
119
+ end
120
+
121
+ @engine.wait_for(:alpha)
122
+
123
+ sp.reply(sp.first)
124
+
125
+ @engine.wait_for(wfid)
126
+
127
+ sleep 0.100
128
+
129
+ assert_equal %w[ that this ], seen.sort
130
+ assert_equal [], @engine.context.logger.instance_variable_get(:@waiting)
131
+ end
99
132
  end
100
133