ruote 2.2.0 → 2.3.0
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.
- data/CHANGELOG.txt +166 -1
- data/CREDITS.txt +36 -17
- data/LICENSE.txt +1 -1
- data/README.rdoc +1 -7
- data/Rakefile +38 -29
- data/TODO.txt +93 -52
- data/lib/ruote-fs.rb +3 -0
- data/lib/ruote.rb +5 -1
- data/lib/ruote/context.rb +140 -35
- data/lib/ruote/dashboard.rb +1247 -0
- data/lib/ruote/{engine → dboard}/process_error.rb +22 -2
- data/lib/ruote/dboard/process_status.rb +587 -0
- data/lib/ruote/engine.rb +6 -871
- data/lib/ruote/exp/command.rb +7 -2
- data/lib/ruote/exp/commanded.rb +2 -2
- data/lib/ruote/exp/condition.rb +38 -13
- data/lib/ruote/exp/fe_add_branches.rb +1 -1
- data/lib/ruote/exp/fe_apply.rb +1 -1
- data/lib/ruote/exp/fe_await.rb +357 -0
- data/lib/ruote/exp/fe_cancel_process.rb +17 -3
- data/lib/ruote/exp/fe_command.rb +8 -4
- data/lib/ruote/exp/fe_concurrence.rb +218 -18
- data/lib/ruote/exp/fe_concurrent_iterator.rb +71 -10
- data/lib/ruote/exp/fe_cron.rb +3 -10
- data/lib/ruote/exp/fe_cursor.rb +14 -4
- data/lib/ruote/exp/fe_define.rb +3 -1
- data/lib/ruote/exp/fe_echo.rb +1 -1
- data/lib/ruote/exp/fe_equals.rb +1 -1
- data/lib/ruote/exp/fe_error.rb +1 -1
- data/lib/ruote/exp/fe_filter.rb +163 -4
- data/lib/ruote/exp/fe_forget.rb +21 -4
- data/lib/ruote/exp/fe_given.rb +1 -1
- data/lib/ruote/exp/fe_if.rb +1 -1
- data/lib/ruote/exp/fe_inc.rb +102 -35
- data/lib/ruote/exp/fe_iterator.rb +47 -12
- data/lib/ruote/exp/fe_listen.rb +96 -11
- data/lib/ruote/exp/fe_lose.rb +31 -4
- data/lib/ruote/exp/fe_noop.rb +1 -1
- data/lib/ruote/exp/fe_on_error.rb +109 -0
- data/lib/ruote/exp/fe_once.rb +10 -19
- data/lib/ruote/exp/fe_participant.rb +90 -28
- data/lib/ruote/exp/fe_read.rb +69 -0
- data/lib/ruote/exp/fe_redo.rb +3 -2
- data/lib/ruote/exp/fe_ref.rb +57 -27
- data/lib/ruote/exp/fe_registerp.rb +1 -3
- data/lib/ruote/exp/fe_reserve.rb +1 -1
- data/lib/ruote/exp/fe_restore.rb +6 -6
- data/lib/ruote/exp/fe_save.rb +12 -19
- data/lib/ruote/exp/fe_sequence.rb +38 -2
- data/lib/ruote/exp/fe_set.rb +143 -40
- data/lib/ruote/exp/{fe_let.rb → fe_stall.rb} +7 -38
- data/lib/ruote/exp/fe_subprocess.rb +8 -2
- data/lib/ruote/exp/fe_that.rb +1 -1
- data/lib/ruote/exp/fe_undo.rb +40 -4
- data/lib/ruote/exp/fe_unregisterp.rb +1 -3
- data/lib/ruote/exp/fe_wait.rb +12 -25
- data/lib/ruote/exp/{flowexpression.rb → flow_expression.rb} +375 -229
- data/lib/ruote/exp/iterator.rb +2 -2
- data/lib/ruote/exp/merge.rb +78 -17
- data/lib/ruote/exp/ro_attributes.rb +46 -36
- data/lib/ruote/exp/ro_filters.rb +34 -8
- data/lib/ruote/exp/ro_on_x.rb +431 -0
- data/lib/ruote/exp/ro_persist.rb +19 -7
- data/lib/ruote/exp/ro_timers.rb +123 -0
- data/lib/ruote/exp/ro_variables.rb +90 -29
- data/lib/ruote/fei.rb +57 -3
- data/lib/ruote/fs.rb +3 -0
- data/lib/ruote/id/mnemo_wfid_generator.rb +30 -7
- data/lib/ruote/id/wfid_generator.rb +17 -38
- data/lib/ruote/log/default_history.rb +23 -9
- data/lib/ruote/log/fancy_printing.rb +265 -0
- data/lib/ruote/log/storage_history.rb +23 -13
- data/lib/ruote/log/wait_logger.rb +224 -17
- data/lib/ruote/observer.rb +82 -0
- data/lib/ruote/part/block_participant.rb +65 -28
- data/lib/ruote/part/code_participant.rb +81 -0
- data/lib/ruote/part/engine_participant.rb +7 -2
- data/lib/ruote/part/local_participant.rb +221 -21
- data/lib/ruote/part/no_op_participant.rb +1 -1
- data/lib/ruote/part/null_participant.rb +1 -1
- data/lib/ruote/part/participant.rb +50 -0
- data/lib/ruote/part/rev_participant.rb +178 -0
- data/lib/ruote/part/smtp_participant.rb +2 -2
- data/lib/ruote/part/storage_participant.rb +228 -60
- data/lib/ruote/part/template.rb +1 -1
- data/lib/ruote/participant.rb +2 -0
- data/lib/ruote/reader.rb +205 -68
- data/lib/ruote/reader/json.rb +49 -0
- data/lib/ruote/reader/radial.rb +303 -0
- data/lib/ruote/reader/ruby_dsl.rb +44 -9
- data/lib/ruote/reader/xml.rb +11 -8
- data/lib/ruote/receiver/base.rb +98 -45
- data/lib/ruote/storage/base.rb +104 -35
- data/lib/ruote/storage/composite_storage.rb +50 -60
- data/lib/ruote/storage/fs_storage.rb +25 -34
- data/lib/ruote/storage/hash_storage.rb +38 -36
- data/lib/ruote/svc/dispatch_pool.rb +104 -35
- data/lib/ruote/svc/dollar_sub.rb +10 -8
- data/lib/ruote/svc/error_handler.rb +108 -52
- data/lib/ruote/svc/expression_map.rb +3 -3
- data/lib/ruote/svc/participant_list.rb +160 -55
- data/lib/ruote/svc/tracker.rb +31 -31
- data/lib/ruote/svc/treechecker.rb +28 -16
- data/lib/ruote/tree_dot.rb +1 -1
- data/lib/ruote/util/deep.rb +143 -0
- data/lib/ruote/util/filter.rb +125 -18
- data/lib/ruote/util/hashdot.rb +15 -13
- data/lib/ruote/util/look.rb +1 -1
- data/lib/ruote/util/lookup.rb +60 -22
- data/lib/ruote/util/misc.rb +63 -18
- data/lib/ruote/util/mpatch.rb +53 -0
- data/lib/ruote/util/ometa.rb +1 -2
- data/lib/ruote/util/process_observer.rb +177 -0
- data/lib/ruote/util/subprocess.rb +1 -1
- data/lib/ruote/util/time.rb +2 -2
- data/lib/ruote/util/tree.rb +64 -2
- data/lib/ruote/version.rb +3 -2
- data/lib/ruote/worker.rb +421 -92
- data/lib/ruote/workitem.rb +157 -22
- data/ruote.gemspec +15 -9
- data/test/bm/ci.rb +0 -2
- data/test/bm/ici.rb +0 -2
- data/test/bm/load_26c.rb +0 -3
- data/test/bm/mega.rb +0 -2
- data/test/functional/base.rb +57 -43
- data/test/functional/concurrent_base.rb +16 -13
- data/test/functional/ct_0_concurrence.rb +7 -11
- data/test/functional/ct_1_iterator.rb +9 -11
- data/test/functional/ct_2_cancel.rb +28 -17
- data/test/functional/eft_0_flow_expression.rb +35 -0
- data/test/functional/eft_10_cancel_process.rb +1 -1
- data/test/functional/eft_11_wait.rb +13 -13
- data/test/functional/eft_12_listen.rb +199 -66
- data/test/functional/eft_13_iterator.rb +95 -29
- data/test/functional/eft_14_cursor.rb +74 -24
- data/test/functional/eft_15_loop.rb +7 -7
- data/test/functional/eft_16_if.rb +1 -1
- data/test/functional/eft_17_equals.rb +1 -1
- data/test/functional/eft_18_concurrent_iterator.rb +156 -68
- data/test/functional/eft_19_reserve.rb +15 -15
- data/test/functional/eft_1_echo.rb +1 -1
- data/test/functional/eft_20_save.rb +51 -9
- data/test/functional/eft_21_restore.rb +1 -1
- data/test/functional/eft_22_noop.rb +1 -1
- data/test/functional/eft_23_apply.rb +1 -1
- data/test/functional/eft_24_add_branches.rb +7 -8
- data/test/functional/eft_25_command.rb +1 -1
- data/test/functional/eft_26_error.rb +11 -11
- data/test/functional/eft_27_inc.rb +111 -67
- data/test/functional/eft_28_once.rb +16 -16
- data/test/functional/eft_29_cron.rb +9 -9
- data/test/functional/eft_2_sequence.rb +23 -4
- data/test/functional/eft_30_ref.rb +36 -24
- data/test/functional/eft_31_registerp.rb +24 -24
- data/test/functional/eft_32_lose.rb +46 -20
- data/test/functional/eft_34_given.rb +1 -1
- data/test/functional/eft_35_filter.rb +161 -7
- data/test/functional/eft_36_read.rb +97 -0
- data/test/functional/{eft_0_process_definition.rb → eft_37_process_definition.rb} +4 -4
- data/test/functional/eft_38_on_error.rb +195 -0
- data/test/functional/eft_39_stall.rb +35 -0
- data/test/functional/eft_3_participant.rb +77 -22
- data/test/functional/eft_40_await.rb +297 -0
- data/test/functional/eft_4_set.rb +110 -11
- data/test/functional/eft_5_subprocess.rb +27 -5
- data/test/functional/eft_6_concurrence.rb +299 -60
- data/test/functional/eft_7_forget.rb +24 -22
- data/test/functional/eft_8_undo.rb +52 -15
- data/test/functional/eft_9_redo.rb +18 -20
- data/test/functional/ft_0_worker.rb +122 -13
- data/test/functional/ft_10_dollar.rb +77 -16
- data/test/functional/ft_11_recursion.rb +9 -9
- data/test/functional/ft_12_launchitem.rb +7 -9
- data/test/functional/ft_13_variables.rb +125 -22
- data/test/functional/ft_14_re_apply.rb +112 -56
- data/test/functional/ft_15_timeout.rb +64 -33
- data/test/functional/ft_16_participant_params.rb +59 -6
- data/test/functional/ft_17_conditional.rb +68 -2
- data/test/functional/ft_18_kill.rb +48 -30
- data/test/functional/ft_19_participant_code.rb +67 -0
- data/test/functional/ft_1_process_status.rb +222 -150
- data/test/functional/ft_20_storage_participant.rb +445 -44
- data/test/functional/ft_21_forget.rb +21 -26
- data/test/functional/ft_22_process_definitions.rb +8 -6
- data/test/functional/ft_23_load_defs.rb +29 -5
- data/test/functional/ft_24_block_participant.rb +199 -20
- data/test/functional/ft_25_receiver.rb +98 -46
- data/test/functional/ft_26_participant_rtimeout.rb +34 -26
- data/test/functional/ft_27_var_indirection.rb +40 -5
- data/test/functional/ft_28_null_noop_participants.rb +5 -5
- data/test/functional/ft_29_part_template.rb +2 -2
- data/test/functional/ft_2_errors.rb +106 -74
- data/test/functional/ft_30_smtp_participant.rb +7 -7
- data/test/functional/ft_31_part_blocking.rb +11 -11
- data/test/functional/ft_32_scope.rb +50 -0
- data/test/functional/ft_33_participant_subprocess_priority.rb +3 -3
- data/test/functional/ft_34_cursor_rewind.rb +14 -14
- data/test/functional/ft_35_add_service.rb +67 -9
- data/test/functional/ft_36_storage_history.rb +92 -24
- data/test/functional/ft_37_default_history.rb +35 -23
- data/test/functional/ft_38_participant_more.rb +189 -32
- data/test/functional/ft_39_wait_for.rb +25 -25
- data/test/functional/ft_3_participant_registration.rb +235 -107
- data/test/functional/ft_40_wait_logger.rb +105 -18
- data/test/functional/ft_41_participants.rb +13 -12
- data/test/functional/ft_42_storage_copy.rb +12 -12
- data/test/functional/ft_43_participant_on_reply.rb +85 -11
- data/test/functional/ft_44_var_participant.rb +5 -5
- data/test/functional/ft_45_participant_accept.rb +3 -3
- data/test/functional/ft_46_launch_single.rb +17 -17
- data/test/functional/ft_47_wfids.rb +41 -0
- data/test/functional/ft_48_lose.rb +19 -25
- data/test/functional/ft_49_engine_on_error.rb +54 -70
- data/test/functional/ft_4_cancel.rb +84 -26
- data/test/functional/ft_50_engine_config.rb +4 -4
- data/test/functional/ft_51_misc.rb +12 -12
- data/test/functional/ft_52_case.rb +17 -17
- data/test/functional/ft_53_engine_on_terminate.rb +18 -21
- data/test/functional/ft_54_patterns.rb +18 -16
- data/test/functional/ft_55_engine_participant.rb +55 -55
- data/test/functional/ft_56_filter_attribute.rb +90 -52
- data/test/functional/ft_57_rev_participant.rb +252 -0
- data/test/functional/ft_58_workitem.rb +150 -0
- data/test/functional/ft_59_pause.rb +329 -0
- data/test/functional/ft_5_on_error.rb +430 -77
- data/test/functional/ft_60_code_participant.rb +65 -0
- data/test/functional/ft_61_trailing_fields.rb +34 -0
- data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
- data/test/functional/ft_63_participants_221.rb +458 -0
- data/test/functional/ft_64_stash.rb +41 -0
- data/test/functional/ft_65_timers.rb +313 -0
- data/test/functional/ft_66_flank.rb +133 -0
- data/test/functional/ft_67_radial_misc.rb +34 -0
- data/test/functional/ft_68_reput.rb +72 -0
- data/test/functional/ft_69_worker_info.rb +56 -0
- data/test/functional/ft_6_on_cancel.rb +189 -36
- data/test/functional/ft_70_take_and_discard_attributes.rb +94 -0
- data/test/functional/ft_71_retries.rb +144 -0
- data/test/functional/ft_72_on_terminate.rb +60 -0
- data/test/functional/ft_73_raise_msg.rb +107 -0
- data/test/functional/ft_74_respark.rb +106 -0
- data/test/functional/ft_75_context.rb +66 -0
- data/test/functional/ft_76_observer.rb +53 -0
- data/test/functional/ft_77_process_observer.rb +157 -0
- data/test/functional/ft_78_part_participant.rb +37 -0
- data/test/functional/ft_7_tags.rb +238 -50
- data/test/functional/ft_8_participant_consumption.rb +27 -21
- data/test/functional/ft_9_subprocesses.rb +48 -18
- data/test/functional/restart_base.rb +4 -6
- data/test/functional/rt_0_wait.rb +10 -10
- data/test/functional/rt_1_listen.rb +6 -6
- data/test/functional/rt_2_errors.rb +12 -12
- data/test/functional/rt_3_once.rb +17 -12
- data/test/functional/rt_4_cron.rb +17 -17
- data/test/functional/rt_5_timeout.rb +13 -13
- data/test/functional/signals.rb +103 -0
- data/test/functional/storage.rb +730 -0
- data/test/functional/storage_helper.rb +48 -35
- data/test/functional/test.rb +6 -2
- data/test/misc/idle.rb +21 -0
- data/test/misc/light.rb +29 -0
- data/test/path_helper.rb +1 -1
- data/test/test.rb +2 -5
- data/test/test_helper.rb +13 -0
- data/test/unit/test.rb +1 -4
- data/test/unit/ut_0_ruby_reader.rb +25 -9
- data/test/unit/ut_10_participants.rb +47 -0
- data/test/unit/ut_11_lookup.rb +59 -2
- data/test/unit/ut_12_wait_logger.rb +123 -0
- data/test/unit/ut_14_is_uri.rb +1 -1
- data/test/unit/ut_15_util.rb +1 -1
- data/test/unit/ut_16_reader.rb +136 -14
- data/test/unit/ut_17_merge.rb +155 -0
- data/test/unit/ut_19_part_template.rb +1 -1
- data/test/unit/ut_1_fei.rb +11 -2
- data/test/unit/ut_20_composite_storage.rb +27 -1
- data/test/unit/{ut_21_participant_list.rb → ut_21_svc_participant_list.rb} +2 -3
- data/test/unit/ut_22_filter.rb +231 -10
- data/test/unit/ut_23_svc_tracker.rb +48 -0
- data/test/unit/ut_24_radial_reader.rb +458 -0
- data/test/unit/ut_25_process_status.rb +143 -0
- data/test/unit/ut_26_deep.rb +131 -0
- data/test/unit/ut_2_dashboard.rb +114 -0
- data/test/unit/ut_3_worker.rb +54 -0
- data/test/unit/ut_4_expmap.rb +1 -1
- data/test/unit/ut_5_tree.rb +23 -23
- data/test/unit/ut_6_condition.rb +71 -29
- data/test/unit/ut_7_workitem.rb +18 -4
- data/test/unit/ut_8_tree_to_dot.rb +1 -1
- data/test/unit/ut_9_xml_reader.rb +1 -1
- metadata +142 -63
- data/jruby_issue.txt +0 -32
- data/lib/ruote/engine/process_status.rb +0 -403
- data/lib/ruote/log/pretty.rb +0 -165
- data/lib/ruote/log/test_logger.rb +0 -204
- data/lib/ruote/util/serializer.rb +0 -103
- data/phil.txt +0 -14
- data/test/functional/eft_33_let.rb +0 -31
- data/test/functional/ft_19_alias.rb +0 -33
- data/test/functional/ft_47_wfid_generator.rb +0 -54
- data/test/unit/storage.rb +0 -403
- data/test/unit/storages.rb +0 -37
- data/test/unit/ut_13_serializer.rb +0 -65
- data/test/unit/ut_18_engine.rb +0 -47
- data/test/unit/ut_3_wait_logger.rb +0 -39
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
# Wed Oct 28 12:51:04 JST 2009
|
|
6
6
|
#
|
|
7
7
|
|
|
8
|
-
require File.
|
|
9
|
-
require File.
|
|
8
|
+
require File.expand_path('../base', __FILE__)
|
|
9
|
+
require File.expand_path('../restart_base', __FILE__)
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class RtCronTest < Test::Unit::TestCase
|
|
@@ -23,42 +23,42 @@ class RtCronTest < Test::Unit::TestCase
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
@
|
|
26
|
+
@dashboard.variables['text'] = 'pre'
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
#@dashboard.noisy = true
|
|
29
29
|
|
|
30
|
-
wfid = @
|
|
30
|
+
wfid = @dashboard.launch(pdef)
|
|
31
31
|
|
|
32
|
-
wait_for(
|
|
32
|
+
wait_for(5)
|
|
33
33
|
|
|
34
|
-
assert_equal 1, @
|
|
35
|
-
assert_equal 1, @
|
|
34
|
+
assert_equal 1, @dashboard.processes.size
|
|
35
|
+
assert_equal 1, @dashboard.storage.get_many('schedules').size
|
|
36
36
|
|
|
37
|
-
@
|
|
37
|
+
@dashboard.shutdown
|
|
38
38
|
|
|
39
39
|
# restart...
|
|
40
40
|
|
|
41
41
|
start_new_engine
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
#@dashboard.noisy = true
|
|
44
44
|
|
|
45
|
-
@
|
|
45
|
+
@dashboard.variables['text'] = 'post'
|
|
46
46
|
|
|
47
|
-
assert_equal 1, @
|
|
48
|
-
assert_equal 1, @
|
|
47
|
+
assert_equal 1, @dashboard.processes.size
|
|
48
|
+
assert_equal 1, @dashboard.storage.get_many('schedules').size
|
|
49
49
|
|
|
50
|
-
wait_for(
|
|
50
|
+
wait_for(5)
|
|
51
51
|
|
|
52
52
|
assert_match /pre\npost/, @tracer.to_s
|
|
53
53
|
|
|
54
|
-
@
|
|
54
|
+
@dashboard.cancel_process(wfid)
|
|
55
55
|
|
|
56
56
|
while msg = wait_for(wfid)
|
|
57
57
|
break if msg['action'] == 'terminated'
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
assert_equal 0, @
|
|
61
|
-
assert_equal 0, @
|
|
60
|
+
assert_equal 0, @dashboard.processes.size
|
|
61
|
+
assert_equal 0, @dashboard.storage.get_many('schedules').size
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
# Wed Oct 28 14:51:07 JST 2009
|
|
6
6
|
#
|
|
7
7
|
|
|
8
|
-
require File.
|
|
9
|
-
require File.
|
|
8
|
+
require File.expand_path('../base', __FILE__)
|
|
9
|
+
require File.expand_path('../restart_base', __FILE__)
|
|
10
10
|
|
|
11
11
|
require 'ruote/part/null_participant'
|
|
12
12
|
|
|
@@ -25,18 +25,18 @@ class RtTimeoutTest < Test::Unit::TestCase
|
|
|
25
25
|
participant 'alpha', :timeout => '2d'
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
@
|
|
28
|
+
@dashboard.register_participant 'alpha', Ruote::NullParticipant
|
|
29
29
|
|
|
30
30
|
#noisy
|
|
31
31
|
|
|
32
|
-
wfid = @
|
|
32
|
+
wfid = @dashboard.launch(pdef)
|
|
33
33
|
|
|
34
34
|
wait_for(3)
|
|
35
35
|
|
|
36
|
-
assert_equal 1, @
|
|
37
|
-
assert_equal 1, @
|
|
36
|
+
assert_equal 1, @dashboard.processes.size
|
|
37
|
+
assert_equal 1, @dashboard.storage.get_many('schedules').size
|
|
38
38
|
|
|
39
|
-
@
|
|
39
|
+
@dashboard.shutdown
|
|
40
40
|
|
|
41
41
|
# restart...
|
|
42
42
|
|
|
@@ -44,17 +44,17 @@ class RtTimeoutTest < Test::Unit::TestCase
|
|
|
44
44
|
|
|
45
45
|
#noisy
|
|
46
46
|
|
|
47
|
-
@
|
|
47
|
+
@dashboard.register_participant 'alpha', Ruote::NullParticipant
|
|
48
48
|
|
|
49
|
-
assert_equal 1, @
|
|
50
|
-
assert_equal 1, @
|
|
49
|
+
assert_equal 1, @dashboard.processes.size
|
|
50
|
+
assert_equal 1, @dashboard.storage.get_many('schedules').size
|
|
51
51
|
|
|
52
|
-
@
|
|
52
|
+
@dashboard.cancel_process(wfid)
|
|
53
53
|
|
|
54
54
|
wait_for(wfid)
|
|
55
55
|
|
|
56
|
-
assert_equal 0, @
|
|
57
|
-
assert_equal 0, @
|
|
56
|
+
assert_equal 0, @dashboard.processes.size
|
|
57
|
+
assert_equal 0, @dashboard.storage.get_many('schedules').size
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
#
|
|
3
|
+
# testing ruote
|
|
4
|
+
#
|
|
5
|
+
# Sat Sep 20 23:40:10 JST 2008
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Hitting CTRL-C reveals the fancy dashboard log (if any) and the
|
|
10
|
+
# current backtrace.
|
|
11
|
+
#
|
|
12
|
+
trap 'INT' do
|
|
13
|
+
|
|
14
|
+
if $_dashboard && ! (ARGV.include?('-N') || ENV['NOISY'])
|
|
15
|
+
puts
|
|
16
|
+
puts '-' * 80
|
|
17
|
+
puts $_dashboard.context.logger.fancy_log
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
puts
|
|
21
|
+
puts '-' * 80
|
|
22
|
+
puts *caller
|
|
23
|
+
puts '-' * 80
|
|
24
|
+
|
|
25
|
+
exit 1
|
|
26
|
+
|
|
27
|
+
end #if RUBY_VERSION.match(/^1.9./)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Didn't use it much, pops a console while tests are running.
|
|
31
|
+
#
|
|
32
|
+
trap 'USR1' do
|
|
33
|
+
|
|
34
|
+
require 'irb'
|
|
35
|
+
require 'irb/completion'
|
|
36
|
+
|
|
37
|
+
IRB.setup(nil)
|
|
38
|
+
ws = IRB::WorkSpace.new(binding)
|
|
39
|
+
irb = IRB::Irb.new(ws)
|
|
40
|
+
IRB::conf[:MAIN_CONTEXT] = irb.context
|
|
41
|
+
irb.eval_input
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# USR2 is used for CI timeouts. Tries to print a max of useful information
|
|
46
|
+
# and then exits.
|
|
47
|
+
#
|
|
48
|
+
trap 'USR2' do
|
|
49
|
+
|
|
50
|
+
# for CI timeouts
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
|
|
54
|
+
puts
|
|
55
|
+
puts '-' * 80
|
|
56
|
+
puts *$_engine.context.logger.fancy_log if $_engine
|
|
57
|
+
|
|
58
|
+
puts
|
|
59
|
+
puts '-' * 80
|
|
60
|
+
if defined?(MiniTest)
|
|
61
|
+
ObjectSpace.each_object(
|
|
62
|
+
MiniTest::Unit
|
|
63
|
+
).first.instance_eval do
|
|
64
|
+
self.status
|
|
65
|
+
puts
|
|
66
|
+
@report.each_with_index do |msg, i|
|
|
67
|
+
@@out.puts "\n%3d) %s" % [i + 1, msg]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
elsif defined?(Test::Unit::UI::Console::TestRunner)
|
|
71
|
+
ObjectSpace.each_object(
|
|
72
|
+
Test::Unit::UI::Console::TestRunner
|
|
73
|
+
).first.instance_eval do
|
|
74
|
+
finished(-1)
|
|
75
|
+
end
|
|
76
|
+
else
|
|
77
|
+
puts "no test/unit or MiniTest"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
puts '-' * 80
|
|
81
|
+
puts "threads: #{Thread.list.size}"
|
|
82
|
+
Thread.list.each do |t|
|
|
83
|
+
puts '-' * 80
|
|
84
|
+
if Thread.current.respond_to?(:backtrace) # only >= 1.9.2p290 it seems
|
|
85
|
+
puts "thread backtrace:"
|
|
86
|
+
puts *t.backtrace
|
|
87
|
+
else
|
|
88
|
+
t.exit unless t == Thread.main
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
puts '-' * 80
|
|
93
|
+
|
|
94
|
+
rescue Exception => e
|
|
95
|
+
p e
|
|
96
|
+
puts *e.backtrace
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
exit 1
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
puts "pid #{$$}"
|
|
103
|
+
|
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
|
|
2
|
+
#
|
|
3
|
+
# testing ruote
|
|
4
|
+
#
|
|
5
|
+
# Mon Dec 14 15:03:13 JST 2009
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
require File.expand_path('../../test_helper', __FILE__)
|
|
9
|
+
require_json
|
|
10
|
+
require File.expand_path('../../functional/storage_helper', __FILE__)
|
|
11
|
+
require File.expand_path('../../functional/signals', __FILE__)
|
|
12
|
+
require 'ruote'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Please note:
|
|
16
|
+
|
|
17
|
+
# Operations return something trueish when they fail and nil
|
|
18
|
+
# when they succeed.
|
|
19
|
+
#
|
|
20
|
+
# The pattern is: when it fails because the document passed as argument is
|
|
21
|
+
# outdated, you will receive the current version of the document (trueish),
|
|
22
|
+
# when it fails because the document is gone (deleted meanwhile), you will
|
|
23
|
+
# receive true (which is obviously trueish).
|
|
24
|
+
|
|
25
|
+
class FtStorage < Test::Unit::TestCase
|
|
26
|
+
|
|
27
|
+
#
|
|
28
|
+
# test preparation
|
|
29
|
+
|
|
30
|
+
def setup
|
|
31
|
+
|
|
32
|
+
@s = determine_storage({})
|
|
33
|
+
@s = @s.storage if @s.respond_to?(:storage)
|
|
34
|
+
|
|
35
|
+
%w[ errors expressions msgs workitems ].each do |t|
|
|
36
|
+
@s.purge_type!(t)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def teardown
|
|
41
|
+
|
|
42
|
+
return unless @s
|
|
43
|
+
|
|
44
|
+
@s.purge!
|
|
45
|
+
|
|
46
|
+
@s.shutdown
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# helpers
|
|
51
|
+
|
|
52
|
+
def put_toto_doc
|
|
53
|
+
|
|
54
|
+
@s.put('_id' => 'toto', 'type' => 'errors', 'message' => 'testing')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_toto_doc
|
|
58
|
+
|
|
59
|
+
@s.get('errors', 'toto')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# the tests
|
|
64
|
+
|
|
65
|
+
# === put
|
|
66
|
+
|
|
67
|
+
# When successful, #put returns nil.
|
|
68
|
+
#
|
|
69
|
+
def test_put
|
|
70
|
+
|
|
71
|
+
doc = { '_id' => 'toto', 'type' => 'errors', 'message' => 'testing' }
|
|
72
|
+
|
|
73
|
+
r = @s.put(doc)
|
|
74
|
+
|
|
75
|
+
assert_nil r
|
|
76
|
+
|
|
77
|
+
assert_nil doc['_rev']
|
|
78
|
+
assert_nil doc['put_at']
|
|
79
|
+
|
|
80
|
+
doc = @s.get('errors', 'toto')
|
|
81
|
+
|
|
82
|
+
assert_not_nil doc['_rev']
|
|
83
|
+
assert_not_nil doc['put_at']
|
|
84
|
+
|
|
85
|
+
assert_equal 'testing', doc['message']
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# When a document with the same _id and type already existent, the put
|
|
89
|
+
# doesn't happen and #put returns that already existing document.
|
|
90
|
+
#
|
|
91
|
+
def test_put_when_already_existent
|
|
92
|
+
|
|
93
|
+
put_toto_doc
|
|
94
|
+
|
|
95
|
+
doc = { '_id' => 'toto', 'type' => 'errors', 'message' => 'two' }
|
|
96
|
+
|
|
97
|
+
r = @s.put(doc)
|
|
98
|
+
|
|
99
|
+
assert_match /Hash$/, r.class.name
|
|
100
|
+
assert_not_nil r['_rev']
|
|
101
|
+
assert_not_nil r['put_at']
|
|
102
|
+
|
|
103
|
+
assert_nil doc['_rev']
|
|
104
|
+
assert_nil doc['put_at']
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# A successful reput (_id/type/_rev do match) returns nil.
|
|
108
|
+
#
|
|
109
|
+
def test_reput
|
|
110
|
+
|
|
111
|
+
put_toto_doc
|
|
112
|
+
|
|
113
|
+
d0 = get_toto_doc
|
|
114
|
+
|
|
115
|
+
d0['message'] = 'test_reput'
|
|
116
|
+
|
|
117
|
+
r = @s.put(d0)
|
|
118
|
+
|
|
119
|
+
assert_nil r
|
|
120
|
+
|
|
121
|
+
d1 = get_toto_doc
|
|
122
|
+
|
|
123
|
+
assert_not_equal d1['_rev'], d0['_rev']
|
|
124
|
+
assert_not_equal d1['put_at'], d0['put_at']
|
|
125
|
+
|
|
126
|
+
assert_equal 'test_reput', d1['message']
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# A reput with the wrong rev (our document is outdated probably) will
|
|
130
|
+
# not happen and #put will return the current (newest probably) document.
|
|
131
|
+
#
|
|
132
|
+
def test_reput_fail_wrong_rev
|
|
133
|
+
|
|
134
|
+
put_toto_doc
|
|
135
|
+
|
|
136
|
+
d1 = get_toto_doc
|
|
137
|
+
|
|
138
|
+
rev = d1['_rev']
|
|
139
|
+
|
|
140
|
+
@s.put(d1.merge('message' => 'x'))
|
|
141
|
+
|
|
142
|
+
d2 = get_toto_doc
|
|
143
|
+
|
|
144
|
+
r = @s.put(d2.merge('_rev' => rev, 'message' => 'y'))
|
|
145
|
+
|
|
146
|
+
assert_not_nil r
|
|
147
|
+
assert_not_equal d1['_rev'], d2['_rev']
|
|
148
|
+
assert_equal 'x', d2['message']
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Attempting to put a document that is gone (got deleted meanwhile) will
|
|
152
|
+
# return true.
|
|
153
|
+
#
|
|
154
|
+
def test_reput_fail_gone
|
|
155
|
+
|
|
156
|
+
put_toto_doc
|
|
157
|
+
|
|
158
|
+
doc = get_toto_doc
|
|
159
|
+
|
|
160
|
+
@s.delete(doc)
|
|
161
|
+
|
|
162
|
+
r = @s.put(doc)
|
|
163
|
+
|
|
164
|
+
assert_equal true, r
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Attempting to put a document with a _rev directly will raise an
|
|
168
|
+
# ArgumentError.
|
|
169
|
+
#
|
|
170
|
+
def test_put_doc_with_rev
|
|
171
|
+
|
|
172
|
+
put_toto_doc; doc = get_toto_doc
|
|
173
|
+
# just to get a valid _rev
|
|
174
|
+
|
|
175
|
+
r = @s.put(
|
|
176
|
+
'_id' => 'doc_with_rev', 'type' => 'errors', '_rev' => doc['_rev'])
|
|
177
|
+
|
|
178
|
+
assert_equal true, r
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# #put takes an optional :update_rev. When set to true and the put
|
|
182
|
+
# succeeds, the _rev and the put_at of the [local] document are set/updated.
|
|
183
|
+
#
|
|
184
|
+
def test_put_update_rev_new_document
|
|
185
|
+
|
|
186
|
+
doc = { '_id' => 'urev', 'type' => 'errors' }
|
|
187
|
+
|
|
188
|
+
r = @s.put(doc, :update_rev => true)
|
|
189
|
+
|
|
190
|
+
assert_nil r
|
|
191
|
+
assert_not_nil doc['_rev']
|
|
192
|
+
assert_not_nil doc['put_at']
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# When putting a document with the :update_rev option set, the just put
|
|
196
|
+
# document will get the new _rev (and the put_at)
|
|
197
|
+
#
|
|
198
|
+
def test_put_update_rev_existing_document
|
|
199
|
+
|
|
200
|
+
put_toto_doc; doc = get_toto_doc
|
|
201
|
+
|
|
202
|
+
initial_rev = doc['_rev']
|
|
203
|
+
initial_put_at = doc['put_at']
|
|
204
|
+
|
|
205
|
+
r = @s.put(doc, :update_rev => true)
|
|
206
|
+
|
|
207
|
+
assert_nil r
|
|
208
|
+
assert_not_nil initial_rev
|
|
209
|
+
assert_not_nil initial_put_at
|
|
210
|
+
assert_not_nil doc['_rev']
|
|
211
|
+
assert_not_equal doc['_rev'], initial_rev
|
|
212
|
+
assert_not_nil doc['put_at']
|
|
213
|
+
assert_not_equal doc['put_at'], initial_put_at
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# put_at and _rev should not repeat
|
|
217
|
+
#
|
|
218
|
+
def test_put_sequence
|
|
219
|
+
|
|
220
|
+
revs = []
|
|
221
|
+
put_ats = []
|
|
222
|
+
doc = { '_id' => 'putseq', 'type' => 'errors' }
|
|
223
|
+
|
|
224
|
+
77.times do |i|
|
|
225
|
+
|
|
226
|
+
@s.put(doc)
|
|
227
|
+
doc = @s.get('errors', 'putseq')
|
|
228
|
+
|
|
229
|
+
revs << doc['_rev']
|
|
230
|
+
put_ats << doc['put_at']
|
|
231
|
+
|
|
232
|
+
assert_equal i + 1, revs.uniq.size
|
|
233
|
+
assert_equal i + 1, put_ats.uniq.size
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Be lenient with the input (accept symbols, but turn them into strings).
|
|
238
|
+
#
|
|
239
|
+
def test_put_turns_symbols_into_strings
|
|
240
|
+
|
|
241
|
+
r = @s.put('_id' => 'skeys', 'type' => 'errors', :a => :b)
|
|
242
|
+
|
|
243
|
+
assert_nil r
|
|
244
|
+
|
|
245
|
+
doc = @s.get('errors', 'skeys')
|
|
246
|
+
|
|
247
|
+
return if doc.class != Hash
|
|
248
|
+
# MongoDB uses BSON::OrderedHash which is happy with symbols...
|
|
249
|
+
|
|
250
|
+
assert_equal 'b', doc['a']
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# === get
|
|
254
|
+
|
|
255
|
+
# Getting a non-existent document returns nil.
|
|
256
|
+
#
|
|
257
|
+
def test_get_non_existent
|
|
258
|
+
|
|
259
|
+
assert_nil @s.get('errors', 'nemo')
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Getting a document returns it (well the most up-to-date revision of it).
|
|
263
|
+
#
|
|
264
|
+
def test_get
|
|
265
|
+
|
|
266
|
+
put_toto_doc
|
|
267
|
+
|
|
268
|
+
doc = @s.get('errors', 'toto')
|
|
269
|
+
|
|
270
|
+
doc.delete('_rev')
|
|
271
|
+
doc.delete('put_at')
|
|
272
|
+
doc.delete('_wfid') # ruote-mon
|
|
273
|
+
|
|
274
|
+
assert_equal(
|
|
275
|
+
{ '_id' => 'toto', 'type' => 'errors', 'message' => 'testing' },
|
|
276
|
+
doc)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# === delete
|
|
280
|
+
|
|
281
|
+
# When successful, #delete returns nil (like the other methods...).
|
|
282
|
+
#
|
|
283
|
+
def test_delete
|
|
284
|
+
|
|
285
|
+
put_toto_doc
|
|
286
|
+
|
|
287
|
+
doc = @s.get('errors', 'toto')
|
|
288
|
+
|
|
289
|
+
r = @s.delete(doc)
|
|
290
|
+
|
|
291
|
+
assert_equal nil, r
|
|
292
|
+
|
|
293
|
+
doc = @s.get('errors', 'toto')
|
|
294
|
+
|
|
295
|
+
assert_equal nil, doc
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# When attempting to delete a document and that document argument has no
|
|
299
|
+
# _rev, it will raise an ArgumentError.
|
|
300
|
+
#
|
|
301
|
+
def test_delete_document_without_rev
|
|
302
|
+
|
|
303
|
+
assert_raise(
|
|
304
|
+
ArgumentError, "can't delete doc without _rev"
|
|
305
|
+
) do
|
|
306
|
+
@s.delete('_id' => 'without_rev', 'type' => 'errors')
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Deleting a document that doesn't exist returns true.
|
|
311
|
+
#
|
|
312
|
+
def test_delete_non_existent_document
|
|
313
|
+
|
|
314
|
+
put_toto_doc; doc = get_toto_doc
|
|
315
|
+
# just to get a valid _rev
|
|
316
|
+
|
|
317
|
+
r = @s.delete('_id' => 'ned', 'type' => 'errors', '_rev' => doc['_rev'])
|
|
318
|
+
|
|
319
|
+
assert_equal true, r
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# Deleting a document that is gone (got deleted meanwhile) returns true.
|
|
323
|
+
#
|
|
324
|
+
def test_delete_gone_document
|
|
325
|
+
|
|
326
|
+
put_toto_doc
|
|
327
|
+
doc = get_toto_doc
|
|
328
|
+
@s.delete(doc)
|
|
329
|
+
|
|
330
|
+
r = @s.delete(doc)
|
|
331
|
+
|
|
332
|
+
assert_equal true, r
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# === get_many
|
|
336
|
+
|
|
337
|
+
# Get many documents at once, use a string or regex key, or not.
|
|
338
|
+
#
|
|
339
|
+
def test_get_many
|
|
340
|
+
|
|
341
|
+
load_30_errors
|
|
342
|
+
|
|
343
|
+
assert_equal 30, @s.get_many('errors').size
|
|
344
|
+
assert_equal 0, @s.get_many('errors', '7').size
|
|
345
|
+
assert_equal 1, @s.get_many('errors', '07').size
|
|
346
|
+
assert_equal 1, @s.get_many('errors', /!07$/).size
|
|
347
|
+
assert_equal 30, @s.get_many('errors', /^yy!/).size
|
|
348
|
+
assert_equal 30, @s.get_many('errors', /y/).size
|
|
349
|
+
|
|
350
|
+
assert_equal 'yy!07', @s.get_many('errors', '07').first['_id']
|
|
351
|
+
assert_equal 'yy!07', @s.get_many('errors', /!07/).first['_id']
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Get many documents at once, use an array of string or regex keys.
|
|
355
|
+
#
|
|
356
|
+
def test_get_many_array_of_keys
|
|
357
|
+
|
|
358
|
+
load_30_errors
|
|
359
|
+
|
|
360
|
+
assert_equal 30, @s.get_many('errors').size
|
|
361
|
+
assert_equal 2, @s.get_many('errors', [ '07', '08' ]).size
|
|
362
|
+
assert_equal 2, @s.get_many('errors', [ /!07$/, /!08$/ ]).size
|
|
363
|
+
|
|
364
|
+
assert_equal(
|
|
365
|
+
%w[ yy!07 yy!08 ],
|
|
366
|
+
@s.get_many('errors', [ '07', '08' ]).collect { |d| d['_id'] }.sort)
|
|
367
|
+
assert_equal(
|
|
368
|
+
%w[ yy!07 yy!08 ],
|
|
369
|
+
@s.get_many('errors', [ /!07$/, /!08$/ ]).collect { |d| d['_id'] }.sort)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Limit the number of documents received.
|
|
373
|
+
#
|
|
374
|
+
def test_get_many_limit
|
|
375
|
+
|
|
376
|
+
load_30_errors
|
|
377
|
+
|
|
378
|
+
assert_equal 10, @s.get_many('errors', nil, :limit => 10).size
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Count the documents (in a type).
|
|
382
|
+
#
|
|
383
|
+
def test_get_many_count
|
|
384
|
+
|
|
385
|
+
load_30_errors
|
|
386
|
+
|
|
387
|
+
assert_equal 30, @s.get_many('errors', nil, :count => true)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# Paginate documents.
|
|
391
|
+
#
|
|
392
|
+
def test_get_many_skip_and_limit
|
|
393
|
+
|
|
394
|
+
load_30_errors
|
|
395
|
+
|
|
396
|
+
assert_equal(
|
|
397
|
+
%w[ yy!01 yy!02 yy!03 yy!04 ],
|
|
398
|
+
@s.get_many(
|
|
399
|
+
'errors', nil, :skip => 0, :limit => 4
|
|
400
|
+
).collect { |d| d['_id'] })
|
|
401
|
+
assert_equal(
|
|
402
|
+
%w[ yy!04 yy!05 yy!06 ],
|
|
403
|
+
@s.get_many(
|
|
404
|
+
'errors', nil, :skip => 3, :limit => 3
|
|
405
|
+
).collect { |d| d['_id'] })
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Pagination and :descending are not incompatible.
|
|
409
|
+
#
|
|
410
|
+
def test_get_many_skip_limit_and_reverse
|
|
411
|
+
|
|
412
|
+
load_30_errors
|
|
413
|
+
|
|
414
|
+
assert_equal(
|
|
415
|
+
%w[ yy!30 yy!29 yy!28 ],
|
|
416
|
+
@s.get_many(
|
|
417
|
+
'errors', nil, :skip => 0, :limit => 3, :descending => true
|
|
418
|
+
).collect { |d| d['_id'] })
|
|
419
|
+
assert_equal(
|
|
420
|
+
%w[ yy!27 yy!26 yy!25 ],
|
|
421
|
+
@s.get_many(
|
|
422
|
+
'errors', nil, :skip => 3, :limit => 3, :descending => true
|
|
423
|
+
).collect { |d| d['_id'] })
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# === purge!
|
|
427
|
+
|
|
428
|
+
# Purge removes all the documents in the storage.
|
|
429
|
+
#
|
|
430
|
+
def test_purge
|
|
431
|
+
|
|
432
|
+
put_toto_doc
|
|
433
|
+
|
|
434
|
+
assert_equal 1, @s.get_many('errors').size
|
|
435
|
+
|
|
436
|
+
@s.purge!
|
|
437
|
+
|
|
438
|
+
assert_equal 0, @s.get_many('errors').size
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# === reserve
|
|
442
|
+
|
|
443
|
+
# Making sure that Storage#reserve(msg) returns true once and only once
|
|
444
|
+
# for a given msg. Stresses the storage for a while and then checks
|
|
445
|
+
# for collisions.
|
|
446
|
+
#
|
|
447
|
+
def test_reserve
|
|
448
|
+
|
|
449
|
+
# TODO: eventually return here if the storage being tested has
|
|
450
|
+
# no need for a real reserve implementation (ruote-swf for example).
|
|
451
|
+
|
|
452
|
+
taoe = Thread.abort_on_exception
|
|
453
|
+
Thread.abort_on_exception = true
|
|
454
|
+
|
|
455
|
+
reserved = []
|
|
456
|
+
threads = []
|
|
457
|
+
|
|
458
|
+
threads << Thread.new do
|
|
459
|
+
i = 0
|
|
460
|
+
loop do
|
|
461
|
+
@s.put_msg('launch', 'tree' => i)
|
|
462
|
+
i = i + 1
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
2.times do
|
|
467
|
+
|
|
468
|
+
threads << Thread.new do
|
|
469
|
+
loop do
|
|
470
|
+
msgs = @s.get_msgs
|
|
471
|
+
msgs[0, 100].each do |msg|
|
|
472
|
+
next if msg['tree'].nil?
|
|
473
|
+
next unless @s.reserve(msg)
|
|
474
|
+
if reserved.include?(msg['tree'])
|
|
475
|
+
puts "=" * 80
|
|
476
|
+
p [ :dbl, :r, msg['_rev'], :t, msg['tree'] ]
|
|
477
|
+
end
|
|
478
|
+
reserved << msg['tree']
|
|
479
|
+
sleep(rand * 0.01)
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
sleep 7
|
|
486
|
+
|
|
487
|
+
threads.each { |t| t.terminate }
|
|
488
|
+
|
|
489
|
+
Thread.abort_on_exception = taoe
|
|
490
|
+
|
|
491
|
+
assert_equal false, reserved.empty?
|
|
492
|
+
assert_equal reserved.size, reserved.uniq.size
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
# === ids
|
|
496
|
+
|
|
497
|
+
# Storage#ids(type) returns all the ids present for a document type, in
|
|
498
|
+
# sorted order.
|
|
499
|
+
#
|
|
500
|
+
def test_ids
|
|
501
|
+
|
|
502
|
+
ids = load_30_errors
|
|
503
|
+
|
|
504
|
+
assert_equal ids.sort, @s.ids('errors')
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
# === dump
|
|
508
|
+
|
|
509
|
+
# #dump returns a string representation of the storage's content. Warning,
|
|
510
|
+
# this is a debug/test method.
|
|
511
|
+
#
|
|
512
|
+
def test_dump
|
|
513
|
+
|
|
514
|
+
load_30_errors
|
|
515
|
+
|
|
516
|
+
dump = @s.dump('errors')
|
|
517
|
+
|
|
518
|
+
assert_match /^[ -] _id: yy!01\n/, dump
|
|
519
|
+
assert_match /^[ -] _id: yy!21\n/, dump
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
# === clear
|
|
523
|
+
|
|
524
|
+
# #clear clears the storage
|
|
525
|
+
#
|
|
526
|
+
def test_clear
|
|
527
|
+
|
|
528
|
+
put_toto_doc
|
|
529
|
+
|
|
530
|
+
assert_equal 1, @s.get_many('errors').size
|
|
531
|
+
|
|
532
|
+
@s.clear
|
|
533
|
+
|
|
534
|
+
assert_equal 0, @s.get_many('errors').size
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
# === remove_process
|
|
538
|
+
|
|
539
|
+
# Put documents for process 0 and process 1, remove_process(1), check that
|
|
540
|
+
# only documents for process 0 are remaining.
|
|
541
|
+
#
|
|
542
|
+
# Don't forget to deal with trackers and schedules.
|
|
543
|
+
#
|
|
544
|
+
def test_remove_process
|
|
545
|
+
|
|
546
|
+
@s.purge_type!('errors')
|
|
547
|
+
ts = @s.get_trackers
|
|
548
|
+
@s.delete(ts) if ts['_rev']
|
|
549
|
+
|
|
550
|
+
dboard = Ruote::Dashboard.new(Ruote::Worker.new(@s))
|
|
551
|
+
dboard.noisy = ENV['NOISY'] == 'true'
|
|
552
|
+
|
|
553
|
+
dboard.register :human, Ruote::StorageParticipant
|
|
554
|
+
|
|
555
|
+
pdef = Ruote.define do
|
|
556
|
+
concurrence do
|
|
557
|
+
wait '1d'
|
|
558
|
+
human
|
|
559
|
+
listen :to => 'bob'
|
|
560
|
+
error 'nada'
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
wfid0 = dboard.launch(pdef)
|
|
565
|
+
wfid1 = dboard.launch(pdef)
|
|
566
|
+
|
|
567
|
+
dboard.wait_for('error_intercepted')
|
|
568
|
+
dboard.wait_for('error_intercepted')
|
|
569
|
+
|
|
570
|
+
assert_equal 12, @s.get_many('expressions').size
|
|
571
|
+
assert_equal 2, @s.get_many('schedules').size
|
|
572
|
+
assert_equal 2, @s.get_many('workitems').size
|
|
573
|
+
assert_equal 2, @s.get_many('errors').size
|
|
574
|
+
assert_equal 2, @s.get_trackers['trackers'].size
|
|
575
|
+
|
|
576
|
+
@s.remove_process(wfid0)
|
|
577
|
+
|
|
578
|
+
assert_equal 6, @s.get_many('expressions').size
|
|
579
|
+
assert_equal 1, @s.get_many('schedules').size
|
|
580
|
+
assert_equal 1, @s.get_many('workitems').size
|
|
581
|
+
assert_equal 1, @s.get_many('errors').size
|
|
582
|
+
assert_equal 1, @s.get_trackers['trackers'].size
|
|
583
|
+
|
|
584
|
+
ensure
|
|
585
|
+
dboard.shutdown rescue nil
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
# === configuration
|
|
589
|
+
|
|
590
|
+
# Simply getting the engine configuration should work.
|
|
591
|
+
#
|
|
592
|
+
def test_get_configuration
|
|
593
|
+
|
|
594
|
+
assert_not_nil @s.get_configuration('engine')
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# The initial configuration passed when initializing the storage overrides
|
|
598
|
+
# any previous configuration.
|
|
599
|
+
#
|
|
600
|
+
def test_override_configuration
|
|
601
|
+
|
|
602
|
+
determine_storage('house' => 'taira', 'domain' => 'harima')
|
|
603
|
+
s = determine_storage('house' => 'minamoto')
|
|
604
|
+
|
|
605
|
+
assert_equal 'minamoto', s.get_configuration('engine')['house']
|
|
606
|
+
assert_equal nil, s.get_configuration('engine')['domain']
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
# Testing the 'preserve_configuration' option for storage initialization.
|
|
610
|
+
#
|
|
611
|
+
def test_preserve_configuration
|
|
612
|
+
|
|
613
|
+
return if @s.class == Ruote::HashStorage
|
|
614
|
+
# this test makes no sense with an in-memory hash
|
|
615
|
+
|
|
616
|
+
determine_storage(
|
|
617
|
+
'house' => 'taira')
|
|
618
|
+
s = determine_storage(
|
|
619
|
+
'house' => 'minamoto', 'preserve_configuration' => true)
|
|
620
|
+
|
|
621
|
+
assert_equal 'taira', s.get_configuration('engine')['house']
|
|
622
|
+
|
|
623
|
+
# if this test is giving a
|
|
624
|
+
# "NoMethodError: undefined method `[]' for nil:NilClass"
|
|
625
|
+
# for ruote-dm, comment out the auto_upgrade! block in
|
|
626
|
+
# ruote-dm/test/functional_connection.rb
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
# === query workitems
|
|
630
|
+
|
|
631
|
+
# Query by workitem field.
|
|
632
|
+
#
|
|
633
|
+
def test_by_field
|
|
634
|
+
|
|
635
|
+
return unless @s.respond_to?(:by_field)
|
|
636
|
+
|
|
637
|
+
load_workitems
|
|
638
|
+
|
|
639
|
+
assert_equal 3, @s.by_field('workitems', 'place', 'kyouto').size
|
|
640
|
+
assert_equal 1, @s.by_field('workitems', 'place', 'sendai').size
|
|
641
|
+
|
|
642
|
+
assert_equal(
|
|
643
|
+
Ruote::Workitem, @s.by_field('workitems', 'place', 'sendai').first.class)
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
# Query by participant name.
|
|
647
|
+
#
|
|
648
|
+
def test_by_participant
|
|
649
|
+
|
|
650
|
+
return unless @s.respond_to?(:by_participant)
|
|
651
|
+
|
|
652
|
+
load_workitems
|
|
653
|
+
|
|
654
|
+
assert_equal 2, @s.by_participant('workitems', 'fujiwara', {}).size
|
|
655
|
+
assert_equal 1, @s.by_participant('workitems', 'shingen', {}).size
|
|
656
|
+
|
|
657
|
+
assert_equal(
|
|
658
|
+
Ruote::Workitem, @s.by_participant('workitems', 'shingen', {}).first.class)
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
# General #query_workitems method.
|
|
662
|
+
#
|
|
663
|
+
def test_query_workitems
|
|
664
|
+
|
|
665
|
+
return unless @s.respond_to?(:query_workitems)
|
|
666
|
+
|
|
667
|
+
load_workitems
|
|
668
|
+
|
|
669
|
+
assert_equal 3, @s.query_workitems('place' => 'kyouto').size
|
|
670
|
+
assert_equal 1, @s.query_workitems('place' => 'kyouto', 'at' => 'kamo').size
|
|
671
|
+
|
|
672
|
+
assert_equal(
|
|
673
|
+
Ruote::Workitem, @s.query_workitems('place' => 'kyouto').first.class)
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
# === misc
|
|
677
|
+
|
|
678
|
+
# Simply make sure the storage (well, at least its "error" type) is empty.
|
|
679
|
+
#
|
|
680
|
+
def test_starts_empty
|
|
681
|
+
|
|
682
|
+
assert_equal 0, @s.get_many('errors').size
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
protected
|
|
686
|
+
|
|
687
|
+
#
|
|
688
|
+
# helpers
|
|
689
|
+
|
|
690
|
+
def load_30_errors
|
|
691
|
+
|
|
692
|
+
(1..30).to_a.shuffle.collect do |i|
|
|
693
|
+
|
|
694
|
+
id = sprintf('yy!%0.2d', i)
|
|
695
|
+
|
|
696
|
+
@s.put(
|
|
697
|
+
'_id' => id,
|
|
698
|
+
'type' => 'errors',
|
|
699
|
+
'msg' => "whatever #{i}",
|
|
700
|
+
'wfid' => id.split('!').last)
|
|
701
|
+
|
|
702
|
+
id
|
|
703
|
+
end
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def put_workitem(wfid, participant_name, fields)
|
|
707
|
+
|
|
708
|
+
@s.put(
|
|
709
|
+
'type' => 'workitems',
|
|
710
|
+
'_id' => "wi!0_0!12ff!#{wfid}",
|
|
711
|
+
'participant_name' => participant_name,
|
|
712
|
+
'wfid' => wfid,
|
|
713
|
+
'fields' => fields)
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
def load_workitems
|
|
717
|
+
|
|
718
|
+
put_workitem(
|
|
719
|
+
'20110218-nadanada', 'fujiwara', 'place' => 'kyouto')
|
|
720
|
+
put_workitem(
|
|
721
|
+
'20110218-nedenada', 'fujiwara', 'place' => 'kyouto', 'at' => 'kamo')
|
|
722
|
+
put_workitem(
|
|
723
|
+
'20110218-nadanodo', 'taira', 'place' => 'kyouto')
|
|
724
|
+
put_workitem(
|
|
725
|
+
'20110218-nodonada', 'date', 'place' => 'sendai')
|
|
726
|
+
put_workitem(
|
|
727
|
+
'20110218-nadanudu', 'shingen', 'place' => 'nagoya')
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
|