ruote-maestrodev 2.2.1

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 (265) hide show
  1. data/CHANGELOG.txt +290 -0
  2. data/CREDITS.txt +99 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.rdoc +88 -0
  5. data/Rakefile +108 -0
  6. data/TODO.txt +488 -0
  7. data/lib/ruote.rb +7 -0
  8. data/lib/ruote/context.rb +194 -0
  9. data/lib/ruote/engine.rb +1062 -0
  10. data/lib/ruote/engine/process_error.rb +122 -0
  11. data/lib/ruote/engine/process_status.rb +448 -0
  12. data/lib/ruote/exp/command.rb +87 -0
  13. data/lib/ruote/exp/commanded.rb +69 -0
  14. data/lib/ruote/exp/condition.rb +227 -0
  15. data/lib/ruote/exp/fe_add_branches.rb +138 -0
  16. data/lib/ruote/exp/fe_apply.rb +154 -0
  17. data/lib/ruote/exp/fe_cancel_process.rb +78 -0
  18. data/lib/ruote/exp/fe_command.rb +156 -0
  19. data/lib/ruote/exp/fe_concurrence.rb +321 -0
  20. data/lib/ruote/exp/fe_concurrent_iterator.rb +219 -0
  21. data/lib/ruote/exp/fe_cron.rb +141 -0
  22. data/lib/ruote/exp/fe_cursor.rb +324 -0
  23. data/lib/ruote/exp/fe_define.rb +112 -0
  24. data/lib/ruote/exp/fe_echo.rb +60 -0
  25. data/lib/ruote/exp/fe_equals.rb +115 -0
  26. data/lib/ruote/exp/fe_error.rb +82 -0
  27. data/lib/ruote/exp/fe_filter.rb +648 -0
  28. data/lib/ruote/exp/fe_forget.rb +88 -0
  29. data/lib/ruote/exp/fe_given.rb +154 -0
  30. data/lib/ruote/exp/fe_if.rb +127 -0
  31. data/lib/ruote/exp/fe_inc.rb +205 -0
  32. data/lib/ruote/exp/fe_iterator.rb +234 -0
  33. data/lib/ruote/exp/fe_let.rb +75 -0
  34. data/lib/ruote/exp/fe_listen.rb +304 -0
  35. data/lib/ruote/exp/fe_lose.rb +110 -0
  36. data/lib/ruote/exp/fe_noop.rb +45 -0
  37. data/lib/ruote/exp/fe_once.rb +215 -0
  38. data/lib/ruote/exp/fe_participant.rb +287 -0
  39. data/lib/ruote/exp/fe_read.rb +69 -0
  40. data/lib/ruote/exp/fe_redo.rb +82 -0
  41. data/lib/ruote/exp/fe_ref.rb +152 -0
  42. data/lib/ruote/exp/fe_registerp.rb +110 -0
  43. data/lib/ruote/exp/fe_reserve.rb +126 -0
  44. data/lib/ruote/exp/fe_restore.rb +102 -0
  45. data/lib/ruote/exp/fe_save.rb +72 -0
  46. data/lib/ruote/exp/fe_sequence.rb +59 -0
  47. data/lib/ruote/exp/fe_set.rb +154 -0
  48. data/lib/ruote/exp/fe_subprocess.rb +211 -0
  49. data/lib/ruote/exp/fe_that.rb +92 -0
  50. data/lib/ruote/exp/fe_undo.rb +67 -0
  51. data/lib/ruote/exp/fe_unregisterp.rb +69 -0
  52. data/lib/ruote/exp/fe_wait.rb +95 -0
  53. data/lib/ruote/exp/flowexpression.rb +886 -0
  54. data/lib/ruote/exp/iterator.rb +81 -0
  55. data/lib/ruote/exp/merge.rb +118 -0
  56. data/lib/ruote/exp/ro_attributes.rb +212 -0
  57. data/lib/ruote/exp/ro_filters.rb +136 -0
  58. data/lib/ruote/exp/ro_persist.rb +154 -0
  59. data/lib/ruote/exp/ro_variables.rb +189 -0
  60. data/lib/ruote/exp/ro_vf.rb +68 -0
  61. data/lib/ruote/fei.rb +260 -0
  62. data/lib/ruote/id/mnemo_wfid_generator.rb +43 -0
  63. data/lib/ruote/id/wfid_generator.rb +81 -0
  64. data/lib/ruote/log/default_history.rb +122 -0
  65. data/lib/ruote/log/pretty.rb +176 -0
  66. data/lib/ruote/log/storage_history.rb +159 -0
  67. data/lib/ruote/log/test_logger.rb +208 -0
  68. data/lib/ruote/log/wait_logger.rb +64 -0
  69. data/lib/ruote/part/block_participant.rb +137 -0
  70. data/lib/ruote/part/code_participant.rb +81 -0
  71. data/lib/ruote/part/engine_participant.rb +189 -0
  72. data/lib/ruote/part/local_participant.rb +138 -0
  73. data/lib/ruote/part/no_op_participant.rb +60 -0
  74. data/lib/ruote/part/null_participant.rb +54 -0
  75. data/lib/ruote/part/rev_participant.rb +169 -0
  76. data/lib/ruote/part/smtp_participant.rb +116 -0
  77. data/lib/ruote/part/storage_participant.rb +392 -0
  78. data/lib/ruote/part/template.rb +84 -0
  79. data/lib/ruote/participant.rb +7 -0
  80. data/lib/ruote/reader.rb +278 -0
  81. data/lib/ruote/reader/json.rb +49 -0
  82. data/lib/ruote/reader/radial.rb +290 -0
  83. data/lib/ruote/reader/ruby_dsl.rb +186 -0
  84. data/lib/ruote/reader/xml.rb +99 -0
  85. data/lib/ruote/receiver/base.rb +212 -0
  86. data/lib/ruote/storage/base.rb +364 -0
  87. data/lib/ruote/storage/composite_storage.rb +121 -0
  88. data/lib/ruote/storage/fs_storage.rb +139 -0
  89. data/lib/ruote/storage/hash_storage.rb +211 -0
  90. data/lib/ruote/svc/dispatch_pool.rb +158 -0
  91. data/lib/ruote/svc/dollar_sub.rb +298 -0
  92. data/lib/ruote/svc/error_handler.rb +138 -0
  93. data/lib/ruote/svc/expression_map.rb +97 -0
  94. data/lib/ruote/svc/participant_list.rb +397 -0
  95. data/lib/ruote/svc/tracker.rb +172 -0
  96. data/lib/ruote/svc/treechecker.rb +141 -0
  97. data/lib/ruote/tree_dot.rb +85 -0
  98. data/lib/ruote/util/filter.rb +525 -0
  99. data/lib/ruote/util/hashdot.rb +79 -0
  100. data/lib/ruote/util/look.rb +128 -0
  101. data/lib/ruote/util/lookup.rb +127 -0
  102. data/lib/ruote/util/misc.rb +167 -0
  103. data/lib/ruote/util/ometa.rb +71 -0
  104. data/lib/ruote/util/serializer.rb +103 -0
  105. data/lib/ruote/util/subprocess.rb +88 -0
  106. data/lib/ruote/util/time.rb +100 -0
  107. data/lib/ruote/util/tree.rb +58 -0
  108. data/lib/ruote/version.rb +29 -0
  109. data/lib/ruote/worker.rb +386 -0
  110. data/lib/ruote/workitem.rb +394 -0
  111. data/phil.txt +14 -0
  112. data/ruote.gemspec +44 -0
  113. data/test/bm/ci.rb +55 -0
  114. data/test/bm/ici.rb +71 -0
  115. data/test/bm/juuman.rb +54 -0
  116. data/test/bm/launch_bench.rb +37 -0
  117. data/test/bm/load_26c.rb +97 -0
  118. data/test/bm/mega.rb +64 -0
  119. data/test/bm/seq_thousand.rb +31 -0
  120. data/test/bm/t.rb +35 -0
  121. data/test/functional/base.rb +247 -0
  122. data/test/functional/concurrent_base.rb +98 -0
  123. data/test/functional/crunner.rb +31 -0
  124. data/test/functional/ct_0_concurrence.rb +65 -0
  125. data/test/functional/ct_1_iterator.rb +67 -0
  126. data/test/functional/ct_2_cancel.rb +81 -0
  127. data/test/functional/eft_0_process_definition.rb +65 -0
  128. data/test/functional/eft_10_cancel_process.rb +46 -0
  129. data/test/functional/eft_11_wait.rb +109 -0
  130. data/test/functional/eft_12_listen.rb +500 -0
  131. data/test/functional/eft_13_iterator.rb +342 -0
  132. data/test/functional/eft_14_cursor.rb +456 -0
  133. data/test/functional/eft_15_loop.rb +69 -0
  134. data/test/functional/eft_16_if.rb +183 -0
  135. data/test/functional/eft_17_equals.rb +55 -0
  136. data/test/functional/eft_18_concurrent_iterator.rb +410 -0
  137. data/test/functional/eft_19_reserve.rb +136 -0
  138. data/test/functional/eft_1_echo.rb +68 -0
  139. data/test/functional/eft_20_save.rb +116 -0
  140. data/test/functional/eft_21_restore.rb +61 -0
  141. data/test/functional/eft_22_noop.rb +28 -0
  142. data/test/functional/eft_23_apply.rb +168 -0
  143. data/test/functional/eft_24_add_branches.rb +98 -0
  144. data/test/functional/eft_25_command.rb +28 -0
  145. data/test/functional/eft_26_error.rb +77 -0
  146. data/test/functional/eft_27_inc.rb +280 -0
  147. data/test/functional/eft_28_once.rb +135 -0
  148. data/test/functional/eft_29_cron.rb +64 -0
  149. data/test/functional/eft_2_sequence.rb +58 -0
  150. data/test/functional/eft_30_ref.rb +155 -0
  151. data/test/functional/eft_31_registerp.rb +130 -0
  152. data/test/functional/eft_32_lose.rb +93 -0
  153. data/test/functional/eft_33_let.rb +31 -0
  154. data/test/functional/eft_34_given.rb +123 -0
  155. data/test/functional/eft_35_filter.rb +375 -0
  156. data/test/functional/eft_36_read.rb +95 -0
  157. data/test/functional/eft_3_participant.rb +149 -0
  158. data/test/functional/eft_4_set.rb +296 -0
  159. data/test/functional/eft_5_subprocess.rb +163 -0
  160. data/test/functional/eft_6_concurrence.rb +304 -0
  161. data/test/functional/eft_7_forget.rb +61 -0
  162. data/test/functional/eft_8_undo.rb +114 -0
  163. data/test/functional/eft_9_redo.rb +138 -0
  164. data/test/functional/ft_0_worker.rb +65 -0
  165. data/test/functional/ft_10_dollar.rb +304 -0
  166. data/test/functional/ft_11_recursion.rb +109 -0
  167. data/test/functional/ft_12_launchitem.rb +43 -0
  168. data/test/functional/ft_13_variables.rb +151 -0
  169. data/test/functional/ft_14_re_apply.rb +324 -0
  170. data/test/functional/ft_15_timeout.rb +226 -0
  171. data/test/functional/ft_16_participant_params.rb +98 -0
  172. data/test/functional/ft_17_conditional.rb +102 -0
  173. data/test/functional/ft_18_kill.rb +138 -0
  174. data/test/functional/ft_19_participant_code.rb +67 -0
  175. data/test/functional/ft_1_process_status.rb +796 -0
  176. data/test/functional/ft_20_storage_participant.rb +543 -0
  177. data/test/functional/ft_21_forget.rb +153 -0
  178. data/test/functional/ft_22_process_definitions.rb +90 -0
  179. data/test/functional/ft_23_load_defs.rb +79 -0
  180. data/test/functional/ft_24_block_participant.rb +235 -0
  181. data/test/functional/ft_25_receiver.rb +207 -0
  182. data/test/functional/ft_26_participant_rtimeout.rb +179 -0
  183. data/test/functional/ft_27_var_indirection.rb +128 -0
  184. data/test/functional/ft_28_null_noop_participants.rb +51 -0
  185. data/test/functional/ft_29_part_template.rb +60 -0
  186. data/test/functional/ft_2_errors.rb +380 -0
  187. data/test/functional/ft_30_smtp_participant.rb +122 -0
  188. data/test/functional/ft_31_part_blocking.rb +72 -0
  189. data/test/functional/ft_33_participant_subprocess_priority.rb +32 -0
  190. data/test/functional/ft_34_cursor_rewind.rb +101 -0
  191. data/test/functional/ft_35_add_service.rb +56 -0
  192. data/test/functional/ft_36_storage_history.rb +150 -0
  193. data/test/functional/ft_37_default_history.rb +109 -0
  194. data/test/functional/ft_38_participant_more.rb +193 -0
  195. data/test/functional/ft_39_wait_for.rb +136 -0
  196. data/test/functional/ft_3_participant_registration.rb +574 -0
  197. data/test/functional/ft_40_wait_logger.rb +62 -0
  198. data/test/functional/ft_41_participants.rb +91 -0
  199. data/test/functional/ft_42_storage_copy.rb +71 -0
  200. data/test/functional/ft_43_participant_on_reply.rb +87 -0
  201. data/test/functional/ft_44_var_participant.rb +35 -0
  202. data/test/functional/ft_45_participant_accept.rb +64 -0
  203. data/test/functional/ft_46_launch_single.rb +83 -0
  204. data/test/functional/ft_47_wfid_generator.rb +54 -0
  205. data/test/functional/ft_48_lose.rb +112 -0
  206. data/test/functional/ft_49_engine_on_error.rb +201 -0
  207. data/test/functional/ft_4_cancel.rb +132 -0
  208. data/test/functional/ft_50_engine_config.rb +22 -0
  209. data/test/functional/ft_51_misc.rb +67 -0
  210. data/test/functional/ft_52_case.rb +134 -0
  211. data/test/functional/ft_53_engine_on_terminate.rb +95 -0
  212. data/test/functional/ft_54_patterns.rb +104 -0
  213. data/test/functional/ft_55_engine_participant.rb +303 -0
  214. data/test/functional/ft_56_filter_attribute.rb +259 -0
  215. data/test/functional/ft_57_rev_participant.rb +252 -0
  216. data/test/functional/ft_58_workitem.rb +69 -0
  217. data/test/functional/ft_59_pause.rb +343 -0
  218. data/test/functional/ft_5_on_error.rb +384 -0
  219. data/test/functional/ft_60_code_participant.rb +45 -0
  220. data/test/functional/ft_61_trailing_fields.rb +34 -0
  221. data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
  222. data/test/functional/ft_6_on_cancel.rb +221 -0
  223. data/test/functional/ft_7_tags.rb +177 -0
  224. data/test/functional/ft_8_participant_consumption.rb +124 -0
  225. data/test/functional/ft_9_subprocesses.rb +146 -0
  226. data/test/functional/restart_base.rb +34 -0
  227. data/test/functional/rt_0_wait.rb +55 -0
  228. data/test/functional/rt_1_listen.rb +56 -0
  229. data/test/functional/rt_2_errors.rb +56 -0
  230. data/test/functional/rt_3_once.rb +70 -0
  231. data/test/functional/rt_4_cron.rb +64 -0
  232. data/test/functional/rt_5_timeout.rb +60 -0
  233. data/test/functional/rtest.rb +8 -0
  234. data/test/functional/storage_helper.rb +93 -0
  235. data/test/functional/test.rb +44 -0
  236. data/test/functional/vertical.rb +46 -0
  237. data/test/path_helper.rb +15 -0
  238. data/test/test.rb +13 -0
  239. data/test/test_helper.rb +28 -0
  240. data/test/unit/storage.rb +428 -0
  241. data/test/unit/storages.rb +37 -0
  242. data/test/unit/test.rb +28 -0
  243. data/test/unit/ut_0_ruby_reader.rb +223 -0
  244. data/test/unit/ut_11_lookup.rb +122 -0
  245. data/test/unit/ut_13_serializer.rb +65 -0
  246. data/test/unit/ut_14_is_uri.rb +28 -0
  247. data/test/unit/ut_15_util.rb +57 -0
  248. data/test/unit/ut_16_reader.rb +225 -0
  249. data/test/unit/ut_18_engine.rb +47 -0
  250. data/test/unit/ut_19_part_template.rb +86 -0
  251. data/test/unit/ut_1_fei.rb +165 -0
  252. data/test/unit/ut_20_composite_storage.rb +74 -0
  253. data/test/unit/ut_21_svc_participant_list.rb +46 -0
  254. data/test/unit/ut_22_filter.rb +1094 -0
  255. data/test/unit/ut_23_svc_tracker.rb +48 -0
  256. data/test/unit/ut_24_radial_reader.rb +332 -0
  257. data/test/unit/ut_25_merge.rb +113 -0
  258. data/test/unit/ut_3_wait_logger.rb +39 -0
  259. data/test/unit/ut_4_expmap.rb +20 -0
  260. data/test/unit/ut_5_tree.rb +54 -0
  261. data/test/unit/ut_6_condition.rb +303 -0
  262. data/test/unit/ut_7_workitem.rb +99 -0
  263. data/test/unit/ut_8_tree_to_dot.rb +72 -0
  264. data/test/unit/ut_9_xml_reader.rb +61 -0
  265. metadata +504 -0
@@ -0,0 +1,109 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Mon Jan 24 11:11:43 JST 2011
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+
11
+ class FtDefaultHistoryTest < Test::Unit::TestCase
12
+ include FunctionalBase
13
+
14
+ def test_engine_has_history
15
+
16
+ assert_not_nil @engine.context.history
17
+ assert_not_nil @engine.history
18
+ end
19
+
20
+ def launch_processes(clear=true)
21
+
22
+ @engine.history.clear! if clear
23
+
24
+ @engine.register_participant 'alpha', Ruote::NullParticipant
25
+
26
+ pdef = Ruote.define do
27
+ alpha
28
+ end
29
+
30
+ wfids = 2.times.collect { @engine.launch(pdef) }
31
+
32
+ @engine.wait_for(:alpha)
33
+ @engine.wait_for(:alpha)
34
+ sleep 0.700
35
+
36
+ wfids
37
+ end
38
+
39
+ def test_all
40
+
41
+ #noisy
42
+
43
+ wfids = launch_processes
44
+
45
+ assert_equal 11, @engine.history.all.size
46
+ end
47
+
48
+ def test_by_wfid
49
+
50
+ wfids = launch_processes
51
+
52
+ assert_equal 4, @engine.history.by_wfid(wfids[0]).size
53
+ assert_not_nil @engine.history.by_wfid(wfids[0]).first['seen_at']
54
+
55
+ assert_equal 4, @engine.history.by_wfid(wfids[1]).size
56
+ end
57
+
58
+ def test_clear!
59
+
60
+ launch_processes
61
+
62
+ assert_equal 11, @engine.history.all.size
63
+
64
+ @engine.history.clear!
65
+
66
+ assert_equal 0, @engine.history.all.size
67
+ end
68
+
69
+ def test_default_range
70
+
71
+ range = @engine.history.range
72
+
73
+ assert_equal Time, range[0].class
74
+ assert_equal range[0], range[1]
75
+ end
76
+
77
+ def test_range
78
+
79
+ launch_processes
80
+ sleep 1
81
+ launch_processes(false)
82
+
83
+ range = @engine.history.range
84
+
85
+ assert_not_equal range[0], range[1]
86
+ assert range[0] < range[1]
87
+ end
88
+
89
+ def test_by_date
90
+
91
+ launch_processes
92
+
93
+ @engine.history.all.each { |msg| msg['seen_at'] = '1970-12-25' }
94
+
95
+ launch_processes(false)
96
+
97
+ assert_equal 22, @engine.history.all.size
98
+
99
+ assert_equal 11, @engine.history.by_date(Time.now).size
100
+ end
101
+
102
+ def test_wfids
103
+
104
+ wfids = launch_processes
105
+
106
+ assert_equal wfids.sort, @engine.history.wfids
107
+ end
108
+ end
109
+
@@ -0,0 +1,193 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Mon Apr 19 14:38:54 JST 2010
6
+ #
7
+ # Qcon Tokyo, special day
8
+ #
9
+
10
+ require File.join(File.dirname(__FILE__), 'base')
11
+
12
+ require 'ruote/part/local_participant'
13
+
14
+
15
+ class FtParticipantMoreTest < Test::Unit::TestCase
16
+ include FunctionalBase
17
+
18
+ class DifficultParticipant
19
+ include Ruote::LocalParticipant
20
+ def initialize(opts)
21
+ end
22
+ def consume(workitem)
23
+ context.tracer << "diff\n"
24
+ if workitem.fields['rejected'].nil?
25
+ workitem.fields['rejected'] = true
26
+ reject(workitem)
27
+ else
28
+ reply_to_engine(workitem)
29
+ end
30
+ end
31
+ end
32
+
33
+ # Reject and re_dispatch are aliases.
34
+ #
35
+ def test_participant_reject
36
+
37
+ pdef = Ruote.process_definition do
38
+ alpha
39
+ end
40
+
41
+ @engine.register_participant :alpha, DifficultParticipant
42
+
43
+ #noisy
44
+
45
+ assert_trace(%w[ diff diff ], pdef)
46
+ end
47
+
48
+ class FightingParticipant
49
+ include Ruote::LocalParticipant
50
+ def initialize(opts)
51
+ end
52
+ def consume(workitem)
53
+ try = workitem.fields['try'] || 0
54
+ context.tracer << "try#{try}\n"
55
+ workitem.fields['try'] = try + 1
56
+ if (try == 0)
57
+ re_dispatch(workitem)
58
+ else
59
+ reply(workitem)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Reject and re_dispatch are aliases.
65
+ #
66
+ def test_participant_re_dispatch
67
+
68
+ pdef = Ruote.process_definition do
69
+ alpha
70
+ end
71
+
72
+ @engine.register_participant :alpha, FightingParticipant
73
+
74
+ #noisy
75
+
76
+ assert_trace(%w[ try0 try1 ], pdef)
77
+ end
78
+
79
+ class RetryParticipant
80
+ include Ruote::LocalParticipant
81
+ def initialize(opts)
82
+ @opts = opts
83
+ end
84
+ def consume(workitem)
85
+ try = workitem.fields['try'] || 0
86
+ context.tracer << "#{Time.now.to_f}\n"
87
+ workitem.fields['try'] = try + 1
88
+ if (try == 0)
89
+ re_dispatch(workitem, :in => @opts['delay'] || '1s')
90
+ else
91
+ reply(workitem)
92
+ end
93
+ end
94
+ def cancel(fei, flavour)
95
+ unschedule_re_dispatch(fei)
96
+ end
97
+ end
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
+ #
104
+ def test_participant_re_dispatch_later
105
+
106
+ pdef = Ruote.process_definition do
107
+ alpha
108
+ end
109
+
110
+ @engine.register_participant :alpha, RetryParticipant
111
+
112
+ #noisy
113
+
114
+ wfid = @engine.launch(pdef)
115
+ wait_for(wfid)
116
+
117
+ times = @tracer.to_s.split("\n").collect { |t| Float(t) }
118
+ t = times.last - times.first
119
+
120
+ assert t >= 1.0, "took less that 1 second"
121
+ assert t < 2.0, "took more than 1.99 second"
122
+ end
123
+
124
+ # Making sure that when a process gets cancelled, its 'later' re-dispatches
125
+ # are cancelled as well.
126
+ #
127
+ def test_participant_re_dispatch_later_cancel
128
+
129
+ pdef = Ruote.process_definition do
130
+ alpha
131
+ end
132
+
133
+ @engine.register_participant :alpha, RetryParticipant, 'delay' => '1m'
134
+
135
+ #noisy
136
+
137
+ wfid = @engine.launch(pdef)
138
+ sleep 0.7
139
+
140
+ @engine.cancel_process(wfid)
141
+ wait_for(wfid)
142
+
143
+ assert_equal 0, @engine.storage.get_many('schedules').size
144
+ end
145
+
146
+ BLACKBOARD = {}
147
+
148
+ class StashingParticipant
149
+ include Ruote::LocalParticipant
150
+ def initialize(opts)
151
+ end
152
+ def consume(workitem)
153
+ put(workitem.fei, 'token' => workitem.params['token'])
154
+ end
155
+ def cancel(fei, flavour)
156
+ BLACKBOARD['token'] = get(fei, 'token')
157
+ BLACKBOARD['all'] = get(fei)
158
+ end
159
+ end
160
+
161
+ # Stashing lets a stateless participant 'stash' state via put() and get()
162
+ # into the engine.
163
+ #
164
+ def test_stash
165
+
166
+ BLACKBOARD.clear
167
+
168
+ pdef = Ruote.process_definition do
169
+ alpha :token => 'of esteem'
170
+ end
171
+
172
+ @engine.register_participant :alpha, StashingParticipant
173
+
174
+ #noisy
175
+
176
+ wfid = @engine.launch(pdef)
177
+ wait_for(:alpha)
178
+
179
+ sleep 0.350 # since wait_for(:alpha) releases too early sometimes
180
+
181
+ ps = @engine.process(wfid)
182
+ fexp = ps.expressions.find { |e| e.fei.expid == '0_0' }
183
+
184
+ assert_equal({ 'token' => 'of esteem' }, fexp.h.stash)
185
+
186
+ @engine.cancel_process(wfid)
187
+ wait_for(wfid)
188
+
189
+ assert_equal('of esteem', BLACKBOARD['token'])
190
+ assert_equal({ 'token' => 'of esteem' }, BLACKBOARD['all'])
191
+ end
192
+ end
193
+
@@ -0,0 +1,136 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Tue Apr 20 12:32:44 JST 2010
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+ require 'ruote/part/storage_participant'
11
+
12
+
13
+ class FtWaitForTest < Test::Unit::TestCase
14
+ include FunctionalBase
15
+
16
+ def test_workitem
17
+
18
+ pdef = Ruote.process_definition :name => 'my process' do
19
+ alpha
20
+ end
21
+
22
+ sp = @engine.register_participant :alpha, Ruote::StorageParticipant
23
+
24
+ #noisy
25
+
26
+ wfid = @engine.launch(pdef)
27
+
28
+ r = wait_for(:alpha)
29
+
30
+ assert_equal(
31
+ Ruote::Workitem,
32
+ @engine.workitem(Ruote.sid(r['fei'])).class)
33
+ end
34
+
35
+ class MyParticipant
36
+ include Ruote::LocalParticipant
37
+ def initialize(opts)
38
+ end
39
+ def consume(workitem)
40
+ sleep rand * 2
41
+ reply_to_engine(workitem)
42
+ end
43
+ end
44
+
45
+ def test_wait_for_empty
46
+
47
+ pdef = Ruote.process_definition :name => 'my process' do
48
+ alpha
49
+ end
50
+
51
+ @engine.register_participant :alpha, MyParticipant
52
+
53
+ 4.times do
54
+ @engine.launch(pdef)
55
+ end
56
+
57
+ #noisy
58
+
59
+ @engine.wait_for(:empty)
60
+
61
+ assert_equal [], @engine.processes
62
+ end
63
+
64
+ def test_wait_for_multiple
65
+
66
+ pdef0 = Ruote.process_definition { alpha }
67
+ pdef1 = Ruote.process_definition { bravo }
68
+
69
+ @engine.register_participant :alpha, MyParticipant
70
+
71
+ #noisy
72
+
73
+ wfids = []
74
+
75
+ 2.times { wfids << @engine.launch(pdef0) }
76
+ 2.times { wfids << @engine.launch(pdef1) }
77
+
78
+ @engine.wait_for(*wfids)
79
+
80
+ assert_equal 2, @engine.processes.size
81
+ end
82
+
83
+ def test_wait_for_inactive
84
+
85
+ pdef0 = Ruote.process_definition { alpha }
86
+ pdef1 = Ruote.process_definition { bravo }
87
+
88
+ @engine.register_participant :alpha, MyParticipant
89
+
90
+ #noisy
91
+
92
+ wfids = []
93
+
94
+ 2.times { @engine.launch(pdef0) }
95
+ 2.times { wfids << @engine.launch(pdef1) }
96
+
97
+ @engine.wait_for(:inactive)
98
+
99
+ assert_equal wfids.sort, @engine.processes.collect { |ps| ps.wfid }.sort
100
+ end
101
+
102
+ def test_wait_for_multithreaded
103
+
104
+ pdef = Ruote.process_definition { alpha }
105
+
106
+ sp = @engine.register_participant :alpha, Ruote::StorageParticipant
107
+
108
+ #noisy
109
+
110
+ wfid = @engine.launch(pdef)
111
+
112
+ seen = []
113
+ threads = []
114
+
115
+ threads << Thread.new do
116
+ @engine.wait_for(wfid)
117
+ seen << 'this'
118
+ end
119
+ threads << Thread.new do
120
+ @engine.wait_for(wfid)
121
+ seen << 'that'
122
+ end
123
+
124
+ @engine.wait_for(:alpha)
125
+
126
+ sp.proceed(sp.first)
127
+
128
+ threads.each do |t|
129
+ t.join
130
+ end
131
+
132
+ assert_equal %w[ that this ], seen.sort
133
+ assert_equal [], @engine.context.logger.instance_variable_get(:@waiting)
134
+ end
135
+ end
136
+
@@ -0,0 +1,574 @@
1
+
2
+ #
3
+ # testing ruote
4
+ #
5
+ # Mon May 18 22:25:57 JST 2009
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+ require 'ruote'
11
+
12
+
13
+ class FtParticipantRegistrationTest < Test::Unit::TestCase
14
+ include FunctionalBase
15
+
16
+ def test_participant_register
17
+
18
+ #noisy
19
+
20
+ @engine.register_participant :alpha do |workitem|
21
+ @tracer << 'alpha'
22
+ end
23
+ @engine.register_participant /^user_/, Ruote::NullParticipant
24
+
25
+ wait_for(2)
26
+
27
+ assert_equal(
28
+ 'participant_registered',
29
+ logger.log[0]['action'])
30
+
31
+ assert_equal(
32
+ %w[ alpha /^user_/ ],
33
+ logger.log.collect { |msg| msg['regex'] })
34
+
35
+ assert_equal(
36
+ [ [ '^alpha$',
37
+ [ 'Ruote::BlockParticipant',
38
+ { 'on_workitem' => "proc do |workitem|\n @tracer << 'alpha'\n end" } ] ],
39
+ [ '^user_',
40
+ [ 'Ruote::NullParticipant',
41
+ {} ] ] ],
42
+ @engine.participant_list.collect { |pe| pe.to_a })
43
+ end
44
+
45
+ def test_participant_register_position
46
+
47
+ @engine.register_participant :ur, Ruote::StorageParticipant
48
+
49
+ assert_equal(
50
+ %w[ ^ur$ ],
51
+ @engine.participant_list.collect { |pe| pe.regex.to_s })
52
+
53
+ @engine.register_participant(
54
+ :first, Ruote::StorageParticipant, :position => :first)
55
+ @engine.register_participant(
56
+ :last, Ruote::StorageParticipant, :position => :last)
57
+
58
+ assert_equal(
59
+ %w[ ^first$ ^ur$ ^last$ ],
60
+ @engine.participant_list.collect { |pe| pe.regex.to_s })
61
+
62
+ @engine.register_participant(
63
+ :x, Ruote::StorageParticipant, :position => -2)
64
+
65
+ assert_equal(
66
+ %w[ ^first$ ^ur$ ^x$ ^last$ ],
67
+ @engine.participant_list.collect { |pe| pe.regex.to_s })
68
+ end
69
+
70
+ def test_participant_register_before
71
+
72
+ @engine.register_participant :alpha, 'AlphaParticipant'
73
+ @engine.register_participant :bravo, 'BravoParticipant'
74
+ @engine.register_participant :alpha, 'AlphaPrimeParticipant', :pos => :after
75
+
76
+ assert_equal(
77
+ [ %w[ ^alpha$ AlphaParticipant ],
78
+ %w[ ^alpha$ AlphaPrimeParticipant ],
79
+ %w[ ^bravo$ BravoParticipant ] ],
80
+ @engine.participant_list.collect { |e| [ e.regex, e.classname ] })
81
+ end
82
+
83
+ def test_participant_register_after
84
+
85
+ @engine.register_participant :alpha, 'AlphaParticipant'
86
+ @engine.register_participant :alpha, 'AlphaPrimeParticipant', :pos => :before
87
+
88
+ assert_equal(
89
+ [ %w[ ^alpha$ AlphaPrimeParticipant ],
90
+ %w[ ^alpha$ AlphaParticipant ] ],
91
+ @engine.participant_list.collect { |e| [ e.regex, e.classname ] })
92
+ end
93
+
94
+ def test_participant_register_before_after_corner_cases
95
+
96
+ @engine.register_participant :alpha, 'KlassA', :pos => :before
97
+ @engine.register_participant :bravo, 'KlassB', :pos => :after
98
+
99
+ assert_equal(
100
+ [ %w[ ^alpha$ KlassA ],
101
+ %w[ ^bravo$ KlassB ] ],
102
+ @engine.participant_list.collect { |e| [ e.regex, e.classname ] })
103
+ end
104
+
105
+ def test_participant_register_over
106
+
107
+ @engine.register_participant :alpha, 'KlassA'
108
+ @engine.register_participant :bravo, 'KlassB'
109
+ @engine.register_participant :alpha, 'KlassAa', :pos => :over
110
+ @engine.register_participant :charly, 'KlassC', :pos => :over
111
+
112
+ assert_equal(
113
+ [ %w[ ^alpha$ KlassAa ],
114
+ %w[ ^bravo$ KlassB ],
115
+ %w[ ^charly$ KlassC ] ],
116
+ @engine.participant_list.collect { |e| [ e.regex, e.classname ] })
117
+ end
118
+
119
+ def test_double_registration
120
+
121
+ @engine.register_participant :alpha do |workitem|
122
+ @tracer << 'alpha'
123
+ end
124
+ @engine.register_participant :alpha do |workitem|
125
+ @tracer << 'alpha'
126
+ end
127
+
128
+ assert_equal 1, @engine.context.plist.send(:get_list)['list'].size
129
+ end
130
+
131
+ def test_register_and_return_something
132
+
133
+ pa = @engine.register_participant :alpha do |workitem|
134
+ end
135
+ pb = @engine.register_participant :bravo, Ruote::StorageParticipant
136
+
137
+ assert_nil pa
138
+ assert_equal Ruote::StorageParticipant, pb.class
139
+ end
140
+
141
+ def test_participant_unregister_by_name
142
+
143
+ #noisy
144
+
145
+ @engine.register_participant :alpha do |workitem|
146
+ end
147
+
148
+ @engine.unregister_participant(:alpha)
149
+
150
+ wait_for(2)
151
+ Thread.pass
152
+
153
+ msg = logger.log.last
154
+ assert_equal 'participant_unregistered', msg['action']
155
+ assert_equal '^alpha$', msg['regex']
156
+ end
157
+
158
+ def test_participant_unregister
159
+
160
+ @engine.register_participant :alpha do |workitem|
161
+ end
162
+
163
+ @engine.unregister_participant('alpha')
164
+
165
+ wait_for(2)
166
+
167
+ msg = logger.log.last
168
+ assert_equal 'participant_unregistered', msg['action']
169
+ assert_equal '^alpha$', msg['regex']
170
+
171
+ assert_equal 0, @engine.context.plist.list.size
172
+ end
173
+
174
+ class MyParticipant
175
+ @@down = false
176
+ def self.down
177
+ @@down
178
+ end
179
+ def initialize
180
+ end
181
+ def shutdown
182
+ @@down = true
183
+ end
184
+ end
185
+
186
+ def test_participant_shutdown
187
+
188
+ alpha = @engine.register :alpha, MyParticipant
189
+
190
+ @engine.context.plist.shutdown
191
+
192
+ assert_equal true, MyParticipant.down
193
+ end
194
+
195
+ def test_participant_list_of_names
196
+
197
+ pa = @engine.register_participant :alpha do |workitem|
198
+ end
199
+
200
+ assert_equal [ '^alpha$' ], @engine.context.plist.names
201
+ end
202
+
203
+ def test_register_require_path
204
+
205
+ rpath = File.join(
206
+ File.dirname(__FILE__), "#{Time.now.to_f}_#{$$}_required_participant")
207
+ path = "#{rpath}.rb"
208
+
209
+ File.open(path, 'wb') do |f|
210
+ f.write(%{
211
+ class RequiredParticipant
212
+ include Ruote::LocalParticipant
213
+ def initialize(opts)
214
+ @opts = opts
215
+ end
216
+ def consume(workitem)
217
+ workitem.fields['message'] = @opts['message']
218
+ reply(workitem)
219
+ end
220
+ end
221
+ })
222
+ end
223
+
224
+ @engine.register_participant(
225
+ :alfred,
226
+ 'RequiredParticipant',
227
+ :require_path => rpath, :message => 'hello')
228
+
229
+ assert_equal [ '^alfred$' ], @engine.context.plist.names
230
+
231
+ # first run
232
+
233
+ assert_equal(
234
+ [ 'RequiredParticipant',
235
+ { 'require_path' => rpath, 'message' => 'hello' } ],
236
+ @engine.context.plist.lookup_info('alfred', nil))
237
+
238
+ wfid = @engine.launch(Ruote.define { alfred })
239
+ r = @engine.wait_for(wfid)
240
+
241
+ assert_equal 'hello', r['workitem']['fields']['message']
242
+
243
+ # second run
244
+
245
+ File.open(path, 'wb') do |f|
246
+ f.write(%{
247
+ class RequiredParticipant
248
+ include Ruote::LocalParticipant
249
+ def initialize(opts)
250
+ @opts = opts
251
+ end
252
+ def consume(workitem)
253
+ workitem.fields['message'] = 'second run'
254
+ reply(workitem)
255
+ end
256
+ end
257
+ })
258
+ end
259
+
260
+ wfid = @engine.launch(Ruote.define { alfred })
261
+ r = @engine.wait_for(wfid)
262
+
263
+ # since it's a 'require', the code isn't reloaded
264
+
265
+ assert_equal 'hello', r['workitem']['fields']['message']
266
+
267
+ FileUtils.rm(path)
268
+ end
269
+
270
+ def test_reqister_load_path
271
+
272
+ path = File.join(
273
+ File.dirname(__FILE__), "#{Time.now.to_f}_#{$$}_loaded_participant.rb")
274
+
275
+ File.open(path, 'wb') do |f|
276
+ f.write(%{
277
+ class LoadedParticipant
278
+ include Ruote::LocalParticipant
279
+ def initialize(opts)
280
+ @opts = opts
281
+ end
282
+ def consume(workitem)
283
+ workitem.fields['message'] = @opts['message']
284
+ reply(workitem)
285
+ end
286
+ end
287
+ })
288
+ end
289
+
290
+ @engine.register_participant(
291
+ :alfred,
292
+ 'LoadedParticipant',
293
+ :load_path => path, :message => 'bondzoi')
294
+
295
+ assert_equal [ '^alfred$' ], @engine.context.plist.names
296
+
297
+ # first run
298
+
299
+ assert_equal(
300
+ [ 'LoadedParticipant',
301
+ { 'load_path' => path, 'message' => 'bondzoi' } ],
302
+ @engine.context.plist.lookup_info('alfred', nil))
303
+
304
+ wfid = @engine.launch(Ruote.define { alfred })
305
+ r = @engine.wait_for(wfid)
306
+
307
+ assert_equal 'bondzoi', r['workitem']['fields']['message']
308
+
309
+ # second run
310
+
311
+ File.open(path, 'wb') do |f|
312
+ f.write(%{
313
+ class LoadedParticipant
314
+ include Ruote::LocalParticipant
315
+ def initialize(opts)
316
+ @opts = opts
317
+ end
318
+ def consume(workitem)
319
+ workitem.fields['message'] = 'second run'
320
+ reply(workitem)
321
+ end
322
+ end
323
+ })
324
+ end
325
+
326
+ wfid = @engine.launch(Ruote.define { alfred })
327
+ r = @engine.wait_for(wfid)
328
+
329
+ # since it's a 'load', the code is reloaded
330
+
331
+ assert_equal 'second run', r['workitem']['fields']['message']
332
+
333
+ FileUtils.rm(path)
334
+ end
335
+
336
+ def test_participant_list
337
+
338
+ #noisy
339
+
340
+ @engine.register_participant 'alpha', Ruote::StorageParticipant
341
+
342
+ assert_equal(
343
+ [ '/^alpha$/ ==> Ruote::StorageParticipant {}' ],
344
+ @engine.participant_list.collect { |pe| pe.to_s })
345
+
346
+ # launching a process with a missing participant
347
+
348
+ wfid = @engine.launch(Ruote.define { bravo })
349
+ @engine.wait_for(wfid)
350
+
351
+ assert_equal 1, @engine.process(wfid).errors.size
352
+
353
+ # fixing the error by updating the participant list
354
+
355
+ list = @engine.participant_list
356
+ list.first.regex = '^.+$' # instead of '^alpha$'
357
+ @engine.participant_list = list
358
+
359
+ # replay at error
360
+
361
+ @engine.replay_at_error(@engine.process(wfid).errors.first)
362
+ @engine.wait_for(:bravo)
363
+
364
+ # bravo should hold a workitem
365
+
366
+ assert_equal 1, @engine.storage_participant.size
367
+ assert_equal 'bravo', @engine.storage_participant.first.participant_name
368
+ end
369
+
370
+ def test_participant_list_update
371
+
372
+ @engine.register_participant 'alpha', Ruote::StorageParticipant
373
+
374
+ assert_equal(
375
+ [ '/^alpha$/ ==> Ruote::StorageParticipant {}' ],
376
+ @engine.participant_list.collect { |pe| pe.to_s })
377
+
378
+ # 0
379
+
380
+ @engine.participant_list = [
381
+ { 'regex' => '^bravo$',
382
+ 'classname' => 'Ruote::StorageParticipant',
383
+ 'options' => {} },
384
+ { 'regex' => '^charly$',
385
+ 'classname' => 'Ruote::StorageParticipant',
386
+ 'options' => {} }
387
+ ]
388
+
389
+ assert_equal(
390
+ [
391
+ '/^bravo$/ ==> Ruote::StorageParticipant {}',
392
+ '/^charly$/ ==> Ruote::StorageParticipant {}'
393
+ ],
394
+ @engine.participant_list.collect { |pe| pe.to_s })
395
+
396
+ # 1
397
+
398
+ @engine.participant_list = [
399
+ [ '^charly$', [ 'Ruote::StorageParticipant', {} ] ],
400
+ [ '^bravo$', [ 'Ruote::StorageParticipant', {} ] ]
401
+ ]
402
+
403
+ assert_equal(
404
+ [
405
+ '/^charly$/ ==> Ruote::StorageParticipant {}',
406
+ '/^bravo$/ ==> Ruote::StorageParticipant {}'
407
+ ],
408
+ @engine.participant_list.collect { |pe| pe.to_s })
409
+
410
+ # 2
411
+
412
+ @engine.participant_list = [
413
+ [ '^delta$', Ruote::StorageParticipant, {} ],
414
+ [ '^echo$', 'Ruote::StorageParticipant', {} ]
415
+ ]
416
+
417
+ assert_equal(
418
+ [
419
+ '/^delta$/ ==> Ruote::StorageParticipant {}',
420
+ '/^echo$/ ==> Ruote::StorageParticipant {}'
421
+ ],
422
+ @engine.participant_list.collect { |pe| pe.to_s })
423
+ end
424
+
425
+ class ParticipantCharlie; end
426
+
427
+ def test_register_block
428
+
429
+ @engine.register do
430
+ alpha 'Participants::Alpha', 'flavour' => 'vanilla'
431
+ participant 'bravo', 'Participants::Bravo', :flavour => 'peach'
432
+ participant 'charlie', 'Participants::Charlie'
433
+ participant 'david' do |wi|
434
+ p wi
435
+ end
436
+ catchall 'Participants::Zebda', 'flavour' => 'coconut'
437
+ end
438
+
439
+ assert_equal 5, @engine.participant_list.size
440
+
441
+ assert_equal(
442
+ %w[ ^alpha$ ^bravo$ ^charlie$ ^david$ ^.+$ ],
443
+ @engine.participant_list.collect { |pe| pe.regex.to_s })
444
+
445
+ assert_equal(
446
+ %w[ Participants::Alpha
447
+ Participants::Bravo
448
+ Participants::Charlie
449
+ Ruote::BlockParticipant
450
+ Participants::Zebda ],
451
+ @engine.participant_list.collect { |pe| pe.classname })
452
+
453
+ assert_equal(
454
+ %w[ vanilla peach nil nil coconut ],
455
+ @engine.participant_list.collect { |pe|
456
+ (pe.options['flavour'] || 'nil') rescue 'nil'
457
+ })
458
+ end
459
+
460
+ def test_register_block_and_block
461
+
462
+ @engine.register do
463
+ alpha do |workitem|
464
+ a
465
+ end
466
+ participant 'bravo' do |workitem|
467
+ b
468
+ end
469
+ end
470
+
471
+ assert_equal(
472
+ [ [ 'on_workitem' ], [ 'on_workitem' ] ],
473
+ @engine.participant_list.collect { |pe| pe.options.keys })
474
+ end
475
+
476
+ def test_register_block_catchall_default
477
+
478
+ @engine.register do
479
+ catchall
480
+ end
481
+
482
+ assert_equal(
483
+ %w[ Ruote::StorageParticipant ],
484
+ @engine.participant_list.collect { |pe| pe.classname })
485
+ end
486
+
487
+ def test_register_block_catch_all
488
+
489
+ @engine.register do
490
+ catch_all
491
+ end
492
+
493
+ assert_equal(
494
+ %w[ Ruote::StorageParticipant ],
495
+ @engine.participant_list.collect { |pe| pe.classname })
496
+ end
497
+
498
+ def test_register_block_override_false
499
+
500
+ @engine.register do
501
+ alpha 'KlassA'
502
+ alpha 'KlassB'
503
+ end
504
+
505
+ plist = @engine.participant_list
506
+
507
+ assert_equal(%w[ ^alpha$ ^alpha$ ], plist.collect { |pe| pe.regex })
508
+ assert_equal(%w[ KlassA KlassB ], plist.collect { |pe| pe.classname })
509
+ assert_equal({}, plist.first.options)
510
+ end
511
+
512
+ def test_register_block_clears
513
+
514
+ @engine.register 'alpha', 'AlphaParticipant'
515
+
516
+ @engine.register do
517
+ bravo 'BravoParticipant'
518
+ end
519
+
520
+ assert_equal 1, @engine.participant_list.size
521
+ end
522
+
523
+ def test_register_block_clear_option
524
+
525
+ @engine.register 'alpha', 'AlphaParticipant'
526
+
527
+ @engine.register :clear => false do
528
+ bravo 'BravoParticipant'
529
+ end
530
+
531
+ assert_equal 2, @engine.participant_list.size
532
+ end
533
+
534
+ def test_argument_error_on_instantiated_participant
535
+
536
+ assert_raise ArgumentError do
537
+ @engine.register 'alpha', Ruote::StorageParticipant.new
538
+ end
539
+ assert_raise ArgumentError do
540
+ @engine.register 'alpha', Ruote::StorageParticipant.new, 'hello' => 'kitty'
541
+ end
542
+ end
543
+
544
+ class AaParticipant
545
+ include Ruote::LocalParticipant
546
+ attr_reader :opts
547
+ def initialize(opts)
548
+ @opts = opts
549
+ end
550
+ end
551
+ class BbParticipant < AaParticipant
552
+ def accept?(workitem)
553
+ false
554
+ end
555
+ end
556
+
557
+ def test_engine_participant
558
+
559
+ @engine.register do
560
+ alpha AaParticipant
561
+ bravo BbParticipant
562
+ catchall AaParticipant, :catch_all => 'oh yeah'
563
+ end
564
+
565
+ assert_equal AaParticipant, @engine.participant('alpha').class
566
+ assert_equal BbParticipant, @engine.participant('bravo').class
567
+
568
+ assert_equal AaParticipant, @engine.participant('charly').class
569
+ assert_equal 'oh yeah', @engine.participant('charly').opts['catch_all']
570
+
571
+ assert_equal Ruote::Context, @engine.participant('alpha').context.class
572
+ end
573
+ end
574
+