ruote 2.3.0.1 → 2.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/CHANGELOG.txt +23 -0
  2. data/CREDITS.txt +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/ruote.rb +2 -0
  5. data/lib/ruote/context.rb +2 -1
  6. data/lib/ruote/dashboard.rb +169 -13
  7. data/lib/ruote/dboard/mutation.rb +282 -0
  8. data/lib/ruote/dboard/process_error.rb +1 -1
  9. data/lib/ruote/dboard/process_status.rb +61 -48
  10. data/lib/ruote/engine.rb +1 -1
  11. data/lib/ruote/exp/command.rb +1 -1
  12. data/lib/ruote/exp/commanded.rb +1 -1
  13. data/lib/ruote/exp/condition.rb +2 -1
  14. data/lib/ruote/exp/fe_add_branches.rb +1 -1
  15. data/lib/ruote/exp/fe_apply.rb +1 -1
  16. data/lib/ruote/exp/fe_await.rb +97 -48
  17. data/lib/ruote/exp/fe_cancel_process.rb +1 -1
  18. data/lib/ruote/exp/fe_command.rb +2 -3
  19. data/lib/ruote/exp/fe_concurrence.rb +162 -66
  20. data/lib/ruote/exp/fe_concurrent_iterator.rb +25 -7
  21. data/lib/ruote/exp/fe_cron.rb +1 -1
  22. data/lib/ruote/exp/fe_cursor.rb +10 -11
  23. data/lib/ruote/exp/fe_define.rb +1 -1
  24. data/lib/ruote/exp/fe_echo.rb +1 -1
  25. data/lib/ruote/exp/fe_equals.rb +1 -1
  26. data/lib/ruote/exp/fe_error.rb +1 -1
  27. data/lib/ruote/exp/fe_filter.rb +1 -1
  28. data/lib/ruote/exp/fe_forget.rb +1 -1
  29. data/lib/ruote/exp/fe_given.rb +1 -1
  30. data/lib/ruote/exp/fe_if.rb +87 -7
  31. data/lib/ruote/exp/fe_inc.rb +1 -1
  32. data/lib/ruote/exp/fe_iterator.rb +1 -1
  33. data/lib/ruote/exp/fe_listen.rb +1 -1
  34. data/lib/ruote/exp/fe_lose.rb +1 -1
  35. data/lib/ruote/exp/fe_noop.rb +1 -1
  36. data/lib/ruote/exp/fe_on_error.rb +1 -1
  37. data/lib/ruote/exp/fe_once.rb +1 -1
  38. data/lib/ruote/exp/fe_participant.rb +49 -16
  39. data/lib/ruote/exp/fe_read.rb +1 -1
  40. data/lib/ruote/exp/fe_redo.rb +1 -1
  41. data/lib/ruote/exp/fe_ref.rb +1 -1
  42. data/lib/ruote/exp/fe_registerp.rb +1 -1
  43. data/lib/ruote/exp/fe_reserve.rb +1 -1
  44. data/lib/ruote/exp/fe_restore.rb +1 -7
  45. data/lib/ruote/exp/fe_save.rb +1 -1
  46. data/lib/ruote/exp/fe_sequence.rb +1 -1
  47. data/lib/ruote/exp/fe_set.rb +1 -1
  48. data/lib/ruote/exp/fe_stall.rb +1 -1
  49. data/lib/ruote/exp/fe_subprocess.rb +1 -1
  50. data/lib/ruote/exp/fe_that.rb +1 -1
  51. data/lib/ruote/exp/fe_undo.rb +1 -1
  52. data/lib/ruote/exp/fe_unregisterp.rb +1 -1
  53. data/lib/ruote/exp/fe_wait.rb +1 -1
  54. data/lib/ruote/exp/flow_expression.rb +117 -8
  55. data/lib/ruote/exp/iterator.rb +1 -1
  56. data/lib/ruote/exp/ro_attributes.rb +1 -1
  57. data/lib/ruote/exp/ro_filters.rb +1 -1
  58. data/lib/ruote/exp/ro_on_x.rb +4 -2
  59. data/lib/ruote/exp/ro_persist.rb +1 -1
  60. data/lib/ruote/exp/ro_timers.rb +1 -1
  61. data/lib/ruote/exp/ro_variables.rb +1 -1
  62. data/lib/ruote/extract.rb +125 -0
  63. data/lib/ruote/fei.rb +10 -73
  64. data/lib/ruote/id/mnemo_wfid_generator.rb +1 -1
  65. data/lib/ruote/id/wfid_generator.rb +1 -1
  66. data/lib/ruote/log/default_history.rb +17 -3
  67. data/lib/ruote/log/fancy_printing.rb +12 -32
  68. data/lib/ruote/log/storage_history.rb +1 -1
  69. data/lib/ruote/log/wait_logger.rb +15 -7
  70. data/lib/ruote/merge.rb +123 -0
  71. data/lib/ruote/observer.rb +1 -1
  72. data/lib/ruote/part/block_participant.rb +1 -1
  73. data/lib/ruote/part/code_participant.rb +1 -1
  74. data/lib/ruote/part/engine_participant.rb +1 -1
  75. data/lib/ruote/part/local_participant.rb +9 -1
  76. data/lib/ruote/part/no_op_participant.rb +1 -1
  77. data/lib/ruote/part/null_participant.rb +1 -1
  78. data/lib/ruote/part/participant.rb +1 -1
  79. data/lib/ruote/part/rev_participant.rb +1 -1
  80. data/lib/ruote/part/smtp_participant.rb +1 -1
  81. data/lib/ruote/part/storage_participant.rb +18 -1
  82. data/lib/ruote/part/template.rb +1 -1
  83. data/lib/ruote/reader.rb +1 -1
  84. data/lib/ruote/reader/json.rb +1 -1
  85. data/lib/ruote/reader/radial.rb +4 -4
  86. data/lib/ruote/reader/ruby_dsl.rb +1 -1
  87. data/lib/ruote/reader/xml.rb +1 -1
  88. data/lib/ruote/receiver/base.rb +13 -1
  89. data/lib/ruote/storage/base.rb +8 -14
  90. data/lib/ruote/storage/composite_storage.rb +1 -1
  91. data/lib/ruote/storage/fs_storage.rb +1 -1
  92. data/lib/ruote/storage/hash_storage.rb +2 -1
  93. data/lib/ruote/svc/dispatch_pool.rb +29 -18
  94. data/lib/ruote/svc/dollar_sub.rb +5 -8
  95. data/lib/ruote/svc/error_handler.rb +1 -1
  96. data/lib/ruote/svc/expression_map.rb +1 -1
  97. data/lib/ruote/svc/participant_list.rb +8 -5
  98. data/lib/ruote/svc/tracker.rb +154 -56
  99. data/lib/ruote/svc/treechecker.rb +1 -1
  100. data/lib/ruote/tree_dot.rb +1 -1
  101. data/lib/ruote/util/deep.rb +4 -2
  102. data/lib/ruote/util/filter.rb +1 -1
  103. data/lib/ruote/util/hashdot.rb +1 -1
  104. data/lib/ruote/util/look.rb +1 -1
  105. data/lib/ruote/util/lookup.rb +1 -1
  106. data/lib/ruote/util/misc.rb +51 -1
  107. data/lib/ruote/util/mpatch.rb +1 -1
  108. data/lib/ruote/util/ometa.rb +1 -1
  109. data/lib/ruote/util/subprocess.rb +1 -1
  110. data/lib/ruote/util/time.rb +3 -3
  111. data/lib/ruote/util/tree.rb +43 -4
  112. data/lib/ruote/version.rb +2 -2
  113. data/lib/ruote/worker.rb +30 -18
  114. data/lib/ruote/workitem.rb +1 -1
  115. data/ruote.gemspec +6 -2
  116. data/test/functional/base.rb +0 -1
  117. data/test/functional/concurrent_base.rb +1 -1
  118. data/test/functional/eft_14_cursor.rb +42 -52
  119. data/test/functional/eft_16_if.rb +24 -16
  120. data/test/functional/eft_18_concurrent_iterator.rb +31 -1
  121. data/test/functional/eft_6_concurrence.rb +149 -34
  122. data/test/functional/ft_10_dollar.rb +14 -30
  123. data/test/functional/ft_12_launchitem.rb +15 -0
  124. data/test/functional/ft_1_process_status.rb +62 -13
  125. data/test/functional/ft_20_storage_participant.rb +25 -0
  126. data/test/functional/ft_38_participant_more.rb +1 -1
  127. data/test/functional/ft_42_storage_copy.rb +1 -3
  128. data/test/functional/ft_43_participant_on_reply.rb +63 -5
  129. data/test/functional/ft_66_flank.rb +41 -0
  130. data/test/functional/ft_6_on_cancel.rb +9 -18
  131. data/test/functional/ft_71_retries.rb +25 -12
  132. data/test/functional/ft_79_attach.rb +138 -0
  133. data/test/functional/ft_7_tags.rb +27 -0
  134. data/test/functional/ft_80_pause_on_apply.rb +64 -0
  135. data/test/functional/ft_81_mutation.rb +417 -0
  136. data/test/functional/ft_82_await_attribute.rb +84 -0
  137. data/test/functional/ft_83_trackers.rb +79 -0
  138. data/test/functional/storage.rb +3 -4
  139. data/test/unit/ut_12_wait_logger.rb +41 -3
  140. data/test/unit/ut_15_util.rb +30 -0
  141. data/test/unit/ut_17_merge.rb +54 -53
  142. data/test/unit/ut_1_fei.rb +2 -2
  143. data/test/unit/ut_24_radial_reader.rb +7 -0
  144. data/test/unit/ut_26_deep.rb +14 -0
  145. data/test/unit/ut_5_tree.rb +38 -28
  146. metadata +206 -169
  147. data/couch_url.txt +0 -1
  148. data/lib/ruote/exp/merge.rb +0 -134
@@ -0,0 +1,138 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Wed Oct 3 09:22:39 JST 2012
6
+ #
7
+
8
+ require File.expand_path('../base', __FILE__)
9
+
10
+
11
+ class FtAttachTest < Test::Unit::TestCase
12
+ include FunctionalBase
13
+
14
+ def test_attach
15
+
16
+ @dashboard.register '.+', Ruote::StorageParticipant
17
+
18
+ pdef = Ruote.define do
19
+ set 'v:message' => 'hello world'
20
+ bravo
21
+ end
22
+
23
+ wfid = @dashboard.launch(pdef, 'message' => 'hello planet')
24
+ r = @dashboard.wait_for('dispatched')
25
+
26
+ adef = Ruote.define do
27
+ echo '${v:message}'
28
+ echo '${f:message}'
29
+ end
30
+
31
+ fei = @dashboard.attach(r['fei'], adef)
32
+ r = @dashboard.wait_for('ceased')
33
+
34
+ ps = @dashboard.ps(wfid)
35
+
36
+ assert_equal '0_1_0', fei.expid
37
+ assert_equal wfid, fei.wfid
38
+
39
+ assert_equal "hello world\nhello planet", @tracer.to_s
40
+
41
+ assert_equal 0, ps.errors.size
42
+ assert_equal 2, ps.expressions.size
43
+ assert_equal 1, ps.stored_workitems.size
44
+ end
45
+
46
+ def test_attach_fields_option
47
+
48
+ @dashboard.register '.+', Ruote::StorageParticipant
49
+
50
+ pdef = Ruote.define do
51
+ set 'v:message' => 'hello world'
52
+ bravo
53
+ end
54
+
55
+ wfid = @dashboard.launch(pdef, 'message' => 'hello planet')
56
+ r = @dashboard.wait_for('dispatched')
57
+
58
+ adef = Ruote.define do
59
+ echo '${v:message}'
60
+ echo '${f:message}'
61
+ end
62
+
63
+ fei = @dashboard.attach(r['fei'], adef, :fields => { 'message' => 'nada' })
64
+ r = @dashboard.wait_for('ceased')
65
+ #ps = @dashboard.ps(wfid)
66
+
67
+ assert_equal "hello world\nnada", @tracer.to_s
68
+ end
69
+
70
+ # Well, let's not test those 3 lines of code.
71
+ #
72
+ #def test_attach_merge_fields_option
73
+ #end
74
+
75
+ def test_attach_with_fe
76
+
77
+ @dashboard.register '.+', Ruote::StorageParticipant
78
+
79
+ pdef = Ruote.define do
80
+ set 'v:message' => 'hello world'
81
+ bravo
82
+ end
83
+
84
+ wfid = @dashboard.launch(pdef, 'message' => 'hello planet')
85
+ r = @dashboard.wait_for('dispatched')
86
+
87
+ adef = Ruote.define do
88
+ echo '${v:message}'
89
+ echo '${f:message}'
90
+ end
91
+
92
+ fe = @dashboard.ps(wfid).expressions.last
93
+ fei = @dashboard.attach(fe.h, adef)
94
+ r = @dashboard.wait_for('ceased')
95
+
96
+ ps = @dashboard.ps(wfid)
97
+
98
+ assert_equal '0_1_0', fei.expid
99
+ assert_equal wfid, fei.wfid
100
+
101
+ assert_equal "hello world\nhello planet", @tracer.to_s
102
+
103
+ assert_equal 0, ps.errors.size
104
+ assert_equal 2, ps.expressions.size
105
+ assert_equal 1, ps.stored_workitems.size
106
+ end
107
+
108
+ def test_attach_with_error
109
+
110
+ @dashboard.register '.+', Ruote::NullParticipant
111
+
112
+ pdef = Ruote.define do
113
+ nancy
114
+ end
115
+
116
+ wfid = @dashboard.launch(pdef)
117
+ r = @dashboard.wait_for('dispatched')
118
+
119
+ adef = Ruote.define do
120
+ error 'failing in style'
121
+ end
122
+
123
+ fei = @dashboard.attach(r['fei'], adef)
124
+ r = @dashboard.wait_for('error_intercepted')
125
+
126
+ ps = @dashboard.ps(wfid)
127
+
128
+ assert_equal 1, ps.errors.size
129
+
130
+ @dashboard.cancel(fei)
131
+ r = @dashboard.wait_for('ceased')
132
+
133
+ ps = @dashboard.ps(wfid)
134
+
135
+ assert_equal 0, ps.errors.size
136
+ end
137
+ end
138
+
@@ -361,5 +361,32 @@ class FtTagsTest < Test::Unit::TestCase
361
361
 
362
362
  assert_equal %w[ in_handler handler_out left_tag ], @tracer.to_a
363
363
  end
364
+
365
+ # Those empty tags tests were fixed during the Fukuoka RubyKaigi 01
366
+ # (2012/12/01).
367
+ #
368
+ def test_empty_tag
369
+
370
+ pdef = Ruote.define do
371
+ noop :tag => ''
372
+ end
373
+
374
+ wfid = @dashboard.launch(pdef)
375
+ r = @dashboard.wait_for(wfid)
376
+
377
+ assert_equal 'terminated', r['action']
378
+ end
379
+
380
+ def test_empty_untrimmed_tag
381
+
382
+ pdef = Ruote.define do
383
+ noop :tag => ' '
384
+ end
385
+
386
+ wfid = @dashboard.launch(pdef)
387
+ r = @dashboard.wait_for(wfid)
388
+
389
+ assert_equal 'terminated', r['action']
390
+ end
364
391
  end
365
392
 
@@ -0,0 +1,64 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Sat Oct 13 06:09:12 JST 2012
6
+ #
7
+
8
+ require File.expand_path('../base', __FILE__)
9
+
10
+
11
+ class FtPauseOnApplyTest < Test::Unit::TestCase
12
+ include FunctionalBase
13
+
14
+ def test_pause_apply_then_resume
15
+
16
+ @dashboard.register do
17
+ alpha Ruote::StorageParticipant
18
+ bravo Ruote::NoOpParticipant
19
+ end
20
+
21
+ pdef = Ruote.define do
22
+ echo 'a'
23
+ alpha
24
+ echo 'b'
25
+ bravo :pos => [ 1, 1 ]
26
+ bravo :pos => [ 2, 1 ]
27
+ end
28
+
29
+ wfid = @dashboard.launch(pdef)
30
+ r = @dashboard.wait_for(:alpha)
31
+
32
+ tid = @dashboard.add_tracker(
33
+ wfid,
34
+ 'pre_apply',
35
+ nil,
36
+ { 'tree.1.pos' => [ [ 1, 1 ] ] },
37
+ { '_auto_remove' => true, '_alter' => 'merge', 'state' => 'paused' })
38
+
39
+ assert_equal String, tid.class
40
+
41
+ wi = @dashboard.storage_participant.first
42
+ @dashboard.storage_participant.proceed(wi)
43
+
44
+ @dashboard.wait_for('apply') # echo 'b'
45
+ r = @dashboard.wait_for('apply') # bravo :pos => [ 1, 1 ]
46
+
47
+ assert_equal nil, r['state']
48
+
49
+ ps = @dashboard.ps(wfid)
50
+ bravo = ps.expressions.last
51
+
52
+ assert_equal 'paused', bravo.state
53
+ assert_not_nil bravo.h.paused_apply
54
+
55
+ @dashboard.resume(bravo)
56
+
57
+ r = @dashboard.wait_for(wfid)
58
+
59
+ assert_equal 'terminated', r['action']
60
+
61
+ assert_equal 0, @dashboard.storage.get_trackers['trackers'].size
62
+ end
63
+ end
64
+
@@ -0,0 +1,417 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Tue Oct 30 06:52:44 JST 2012
6
+ #
7
+
8
+ require File.expand_path('../base', __FILE__)
9
+
10
+
11
+ class FtComputeMutationTest < Test::Unit::TestCase
12
+
13
+ #
14
+ # use a transient engine to test the mutation computation
15
+
16
+ def setup
17
+
18
+ @dash = Ruote::Dashboard.new(Ruote::Worker.new(Ruote::HashStorage.new))
19
+ @dash.noisy = ENV['NOISY'] == 'true'
20
+
21
+ @dash.register do
22
+ sam Ruote::StorageParticipant
23
+ nick Ruote::NoOpParticipant
24
+ end
25
+ end
26
+
27
+ def teardown
28
+
29
+ @dash.shutdown
30
+ end
31
+
32
+ def pprint(t0, t1, mutation)
33
+
34
+ puts
35
+ puts '>' + '-' * 79
36
+ p t0
37
+ p t1
38
+ puts mutation
39
+ puts '<' + '-' * 79
40
+ end
41
+
42
+ def print_header
43
+
44
+ return unless ENV['NOISY'] == 'true'
45
+
46
+ puts "\n" + "'" * `stty size`.strip.split(' ').last.to_i
47
+ puts caller[1]
48
+ puts
49
+ end
50
+
51
+ #
52
+ # the tests themselves
53
+
54
+ #
55
+ # sequence testing
56
+
57
+ def launch_nick_nick_sam_sequence
58
+
59
+ print_header
60
+
61
+ @pdef = Ruote.define do
62
+ nick
63
+ nick
64
+ sam
65
+ end
66
+
67
+ @wfid = @dash.launch(@pdef)
68
+ 3.times { @dash.wait_for('dispatched') }
69
+ end
70
+
71
+ def test_sequence_same_tree
72
+
73
+ launch_nick_nick_sam_sequence
74
+
75
+ pdef1 = Ruote.define do
76
+ nick
77
+ nick
78
+ sam
79
+ end
80
+
81
+ mutation = @dash.compute_mutation(@wfid, pdef1)
82
+ a = mutation.to_a
83
+
84
+ #pprint(@pdef, pdef1, mutation)
85
+ assert_equal(0, a.size)
86
+ end
87
+
88
+ def test_sequence_change_post_child
89
+
90
+ launch_nick_nick_sam_sequence
91
+
92
+ pdef1 = Ruote.define do
93
+ nick
94
+ nick
95
+ sam
96
+ nick
97
+ end
98
+
99
+ mutation = @dash.compute_mutation(@wfid, pdef1)
100
+ a = mutation.to_a
101
+
102
+ #pprint(@pdef, pdef1, mutation)
103
+ assert_equal(1, a.size)
104
+ assert_equal(0, Ruote.extract_child_id(a.first['fei']))
105
+ assert_equal(:update, a.first['action'])
106
+ assert_equal(pdef1, a.first['tree'])
107
+ end
108
+
109
+ def test_sequence_change_pre_child
110
+
111
+ launch_nick_nick_sam_sequence
112
+
113
+ pdef1 = Ruote.define do
114
+ nick
115
+ sam
116
+ sam
117
+ end
118
+
119
+ mutation = @dash.compute_mutation(@wfid, pdef1)
120
+ a = mutation.to_a
121
+
122
+ #pprint(@pdef, pdef1, mutation)
123
+ assert_equal(1, a.size)
124
+ assert_equal(0, Ruote.extract_child_id(a.first['fei']))
125
+ assert_equal(:re_apply, a.first['action'])
126
+ assert_equal(pdef1, a.first['tree'])
127
+ end
128
+
129
+ def test_deeper_sequence
130
+
131
+ print_header
132
+
133
+ pdef0 = Ruote.define do
134
+ nick
135
+ sequence do
136
+ nick
137
+ sam
138
+ end
139
+ nick
140
+ end
141
+
142
+ wfid = @dash.launch(pdef0)
143
+ 3.times { @dash.wait_for('dispatched') }
144
+
145
+ ps = @dash.ps(wfid)
146
+
147
+ pdef1 = Ruote.define do
148
+ nick
149
+ sequence do
150
+ nick
151
+ hector
152
+ end
153
+ nick
154
+ end
155
+
156
+ mutation = @dash.compute_mutation(wfid, pdef1)
157
+ a = mutation.to_a
158
+
159
+ #pprint(pdef0, pdef1, mutation)
160
+ assert_equal(3, a.size)
161
+
162
+ assert_equal('0', a[0]['fei'].expid)
163
+ assert_equal(:update, a[0]['action'])
164
+ assert_equal('define', a[0]['tree'].first)
165
+
166
+ assert_equal('0_1', a[1]['fei'].expid)
167
+ assert_equal(:update, a[1]['action'])
168
+ assert_equal('sequence', a[1]['tree'].first)
169
+
170
+ assert_equal('0_1_1', a[2]['fei'].expid)
171
+ assert_equal(:re_apply, a[2]['action'])
172
+ assert_equal('hector', a[2]['tree'].first)
173
+ end
174
+
175
+ def test_mutation_apply
176
+
177
+ print_header
178
+
179
+ pdef0 = Ruote.define do
180
+ sequence do
181
+ nick
182
+ error "nada"
183
+ sam
184
+ end
185
+ end
186
+
187
+ wfid = @dash.launch(pdef0)
188
+ @dash.wait_for('error_intercepted')
189
+
190
+ pdef1 = Ruote.define do
191
+ sequence do
192
+ nick
193
+ nick
194
+ end
195
+ end
196
+
197
+ mutation = @dash.compute_mutation(wfid, pdef1)
198
+ #puts mutation
199
+
200
+ mutation.apply
201
+
202
+ @dash.wait_for('terminated')
203
+
204
+ # the last sam is gone... He didn't get invoked...
205
+ end
206
+
207
+ def test_mutation_apply_force_update
208
+
209
+ print_header
210
+
211
+ pdef0 = Ruote.define do
212
+ sequence do
213
+ nick
214
+ error "nada"
215
+ sam
216
+ end
217
+ end
218
+
219
+ wfid = @dash.launch(pdef0)
220
+ @dash.wait_for('error_intercepted')
221
+
222
+ pdef1 = Ruote.define do
223
+ sequence do
224
+ nick
225
+ nick
226
+ end
227
+ end
228
+
229
+ mutation = @dash.compute_mutation(wfid, pdef1)
230
+
231
+ mutation.apply(:force_update)
232
+
233
+ ps = @dash.ps(wfid)
234
+
235
+ assert_equal(
236
+ [ [ 'define', {}, [
237
+ [ 'sequence', {}, [ ['nick', {}, [] ], ['nick', {}, [] ] ] ] ] ],
238
+ [ 'sequence', {}, [ ['nick', {}, [] ], [ 'nick', {}, [] ] ] ],
239
+ [ 'nick', {}, [] ] ],
240
+ ps.expressions.collect { |e| e.tree })
241
+ end
242
+
243
+ #
244
+ # concurrence testing
245
+
246
+ def launch_sam_sam_concurrence
247
+
248
+ print_header
249
+
250
+ @pdef = Ruote.define do
251
+ concurrence do
252
+ sam
253
+ sam
254
+ end
255
+ end
256
+
257
+ @wfid = @dash.launch(@pdef)
258
+ 2.times { @dash.wait_for('dispatched') }
259
+ end
260
+
261
+ def test_concurrence_add_branch
262
+
263
+ launch_sam_sam_concurrence
264
+
265
+ pdef1 = Ruote.define do
266
+ concurrence do
267
+ sam
268
+ sam
269
+ nick
270
+ end
271
+ end
272
+
273
+ mutation = @dash.compute_mutation(@wfid, pdef1)
274
+ a = mutation.to_a
275
+
276
+ #pprint(@pdef, pdef1, mutation)
277
+ assert_equal(2, a.size)
278
+
279
+ assert_equal('0', a[0]['fei'].expid)
280
+ assert_equal(:update, a[0]['action'])
281
+ assert_equal(pdef1, a[0]['tree'])
282
+
283
+ assert_equal('0_0', a[1]['fei'].expid)
284
+ assert_equal(:re_apply, a[1]['action'])
285
+ assert_equal(pdef1[2][0], a[1]['tree'])
286
+ end
287
+
288
+ def test_concurrence
289
+
290
+ launch_sam_sam_concurrence
291
+
292
+ pdef1 = Ruote.define do
293
+ concurrence do
294
+ sam
295
+ nick
296
+ end
297
+ end
298
+
299
+ mutation = @dash.compute_mutation(@wfid, pdef1)
300
+ a = mutation.to_a
301
+
302
+ #pprint(@pdef, pdef1, mutation)
303
+ assert_equal(3, a.size)
304
+
305
+ assert_equal('0', a[0]['fei'].expid)
306
+ assert_equal(:update, a[0]['action'])
307
+ assert_equal('define', a[0]['tree'][0])
308
+
309
+ assert_equal('0_0', a[1]['fei'].expid)
310
+ assert_equal(:update, a[1]['action'])
311
+ assert_equal('concurrence', a[1]['tree'][0])
312
+
313
+ assert_equal('0_0_1', a[2]['fei'].expid)
314
+ assert_equal(:re_apply, a[2]['action'])
315
+ assert_equal('nick', a[2]['tree'][0])
316
+ end
317
+
318
+ def launch_sam_nick_concurrence
319
+
320
+ print_header
321
+
322
+ @pdef = Ruote.define do
323
+ concurrence do
324
+ sam
325
+ nick
326
+ end
327
+ end
328
+
329
+ @wfid = @dash.launch(@pdef)
330
+ 2.times { @dash.wait_for('dispatched') }
331
+ end
332
+
333
+ def test_concurrence_change_child_that_already_replied
334
+
335
+ launch_sam_nick_concurrence
336
+
337
+ pdef1 = Ruote.define do
338
+ concurrence do
339
+ sam
340
+ sam
341
+ end
342
+ end
343
+
344
+ mutation = @dash.compute_mutation(@wfid, pdef1)
345
+ a = mutation.to_a
346
+
347
+ #pprint(@pdef, pdef1, mutation)
348
+ assert_equal(2, a.size)
349
+
350
+ assert_equal('0', a[0]['fei'].expid)
351
+ assert_equal(:update, a[0]['action'])
352
+ assert_equal('define', a[0]['tree'][0])
353
+
354
+ assert_equal('0_0', a[1]['fei'].expid)
355
+ assert_equal(:re_apply, a[1]['action'])
356
+ assert_equal('concurrence', a[1]['tree'][0])
357
+ end
358
+
359
+ def launch_deep_concurrence
360
+
361
+ print_header
362
+
363
+ @pdef = Ruote.define do
364
+ concurrence do
365
+ sam
366
+ sequence do
367
+ nick
368
+ sam
369
+ end
370
+ end
371
+ end
372
+
373
+ @wfid = @dash.launch(@pdef)
374
+ 2.times { @dash.wait_for('dispatched') }
375
+ end
376
+
377
+ def test_deep_inside_of_concurrence
378
+
379
+ launch_deep_concurrence
380
+
381
+ pdef1 = Ruote.define do
382
+ concurrence do
383
+ sam
384
+ sequence do
385
+ nick
386
+ sam
387
+ sam
388
+ end
389
+ end
390
+ end
391
+
392
+ mutation = @dash.compute_mutation(@wfid, pdef1)
393
+ a = mutation.to_a
394
+
395
+ #pprint(@pdef, pdef1, mutation)
396
+ assert_equal(3, a.size)
397
+
398
+ assert_equal('0', a[0]['fei'].expid)
399
+ assert_equal(:update, a[0]['action'])
400
+ assert_equal('define', a[0]['tree'].first)
401
+
402
+ assert_equal('0_0', a[1]['fei'].expid)
403
+ assert_equal(:update, a[1]['action'])
404
+ assert_equal('concurrence', a[1]['tree'].first)
405
+
406
+ assert_equal('0_0_1', a[2]['fei'].expid)
407
+ assert_equal(:update, a[2]['action'])
408
+
409
+ assert_equal(
410
+ [ 'sequence', {}, [
411
+ [ 'nick', {}, [] ],
412
+ [ 'sam', {}, [] ],
413
+ [ 'sam', {}, [] ] ] ],
414
+ a[2]['tree'])
415
+ end
416
+ end
417
+