ruote 2.3.0.1 → 2.3.0.2

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 (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
+