weel 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/AUTHORS +2 -0
  2. data/COPYING +504 -0
  3. data/FEATURES +20 -0
  4. data/INSTALL +7 -0
  5. data/README +4 -0
  6. data/Rakefile +15 -0
  7. data/example/SimpleHandlerWrapper.rb +68 -0
  8. data/example/SimpleWorkflow.rb +15 -0
  9. data/example/runme.rb +12 -0
  10. data/lib/weel.rb +749 -0
  11. data/test/ContinueTest.rb +25 -0
  12. data/test/TestHandlerWrapper.rb +120 -0
  13. data/test/TestWorkflow.rb +35 -0
  14. data/test/basic/tc_choose.rb +82 -0
  15. data/test/basic/tc_codereplace.rb +38 -0
  16. data/test/basic/tc_data.rb +32 -0
  17. data/test/basic/tc_endpoint.rb +40 -0
  18. data/test/basic/tc_handler.rb +19 -0
  19. data/test/basic/tc_parallel.rb +115 -0
  20. data/test/basic/tc_search.rb +37 -0
  21. data/test/basic/tc_state.rb +17 -0
  22. data/test/basic/tc_wf_control.rb +68 -0
  23. data/test/complex/tc_generalsynchonizingmerge_loopsearch.rb +113 -0
  24. data/test/complex/tc_parallel_stop.rb +32 -0
  25. data/test/wfp_adv_branching/tc_generalizedjoin.rb +11 -0
  26. data/test/wfp_adv_branching/tc_generalsynchronizingmerge.rb +45 -0
  27. data/test/wfp_adv_branching/tc_localsynchronizingmerge.rb +37 -0
  28. data/test/wfp_adv_branching/tc_multichoice_structuredsynchronizingmerge.rb +47 -0
  29. data/test/wfp_adv_branching/tc_multimerge.rb +11 -0
  30. data/test/wfp_adv_branching/tc_structured_discriminator.rb +28 -0
  31. data/test/wfp_adv_branching/tc_structured_partial_join.rb +41 -0
  32. data/test/wfp_adv_branching/tc_threadmerge.rb +11 -0
  33. data/test/wfp_adv_branching/tc_threadsplit.rb +11 -0
  34. data/test/wfp_basic/tc_exclusivechoice_simplemerge.rb +22 -0
  35. data/test/wfp_basic/tc_parallelsplit_synchronization.rb +26 -0
  36. data/test/wfp_basic/tc_sequence.rb +16 -0
  37. data/test/wfp_iteration/tc_structuredloop.rb +65 -0
  38. data/test/wfp_state_based/tc_deferredchoice.rb +38 -0
  39. data/test/wfp_state_based/tc_interleavedparallelrouting.rb +30 -0
  40. data/weel.gemspec +25 -0
  41. metadata +127 -0
@@ -0,0 +1,25 @@
1
+ vim ./wfp_state_based/tc_interleavedparallelrouting.rb
2
+ vim ./wfp_state_based/tc_deferredchoice.rb
3
+ vim ./wfp_iteration/tc_structuredloop.rb
4
+ vim ./wfp_adv_branching
5
+ vim ./wfp_adv_branching/tc_multichoice_structuredsynchronizingmerge.rb
6
+ vim ./wfp_adv_branching/tc_generalsynchronizingmerge.rb
7
+ vim ./wfp_adv_branching/tc_localsynchronizingmerge.rb
8
+ vim ./wfp_adv_branching/tc_threadmerge.rb
9
+ vim ./wfp_adv_branching/tc_generalizedjoin.rb
10
+ vim ./wfp_adv_branching/tc_threadsplit.rb
11
+ vim ./wfp_adv_branching/tc_multimerge.rb
12
+ vim ./wfp_adv_branching/tc_structured_discriminator.rb
13
+ vim ./wfp_adv_branching/tc_structured_partial_join.rb
14
+ vim ./basic/tc_codereplace.rb
15
+ vim ./basic/tc_data.rb
16
+ vim ./basic/tc_handler.rb
17
+ vim ./basic/tc_parallel.rb
18
+ vim ./basic/tc_search.rb
19
+ vim ./basic/tc_endpoint.rb
20
+ vim ./basic/tc_wf_control.rb
21
+ vim ./basic/tc_choose.rb
22
+ vim ./basic/tc_state.rb
23
+ vim ./wfp_basic/tc_exclusivechoice_simplemerge.rb
24
+ vim ./wfp_basic/tc_sequence.rb
25
+ vim ./wfp_basic/tc_parallelsplit_synchronization.rb
@@ -0,0 +1,120 @@
1
+ class TestHandlerWrapper < WEEL::HandlerWrapperBase
2
+ def initialize(args,endpoint=nil,position=nil,continue=nil)
3
+ @__myhandler_stopped = false
4
+ @__myhandler_position = position
5
+ @__myhandler_continue = continue
6
+ @__myhandler_endpoint = endpoint
7
+ @__myhandler_returnValue = nil
8
+ end
9
+
10
+ # executes a ws-call to the given endpoint with the given parameters. the call
11
+ # can be executed asynchron, see finished_call & return_value
12
+ def activity_handle(passthrough, parameters)
13
+ $long_track << "CALL #{@__myhandler_position}: passthrough=[#{passthrough}], endpoint=[#{@__myhandler_endpoint}], parameters=[#{parameters.inspect}]\n"
14
+ $short_track << "C#{@__myhandler_position}"
15
+
16
+ if @__myhandler_endpoint == 'stop it'
17
+ raise WEEL::Signal::Stop
18
+ end
19
+ if parameters[:call]
20
+ @t = Thread.new do
21
+ parameters[:call].call
22
+ @__myhandler_returnValue = parameters.has_key?(:result) ? parameters[:result] : 'Handler_Dummy_Result'
23
+ @__myhandler_continue.continue
24
+ end
25
+ # give nothing back
26
+ else
27
+ @__myhandler_returnValue = parameters.has_key?(:result) ? parameters[:result] : 'Handler_Dummy_Result'
28
+ @__myhandler_continue.continue
29
+ end
30
+ end
31
+
32
+ # returns the result of the last handled call
33
+ def activity_result_value
34
+ @__myhandler_returnValue
35
+ end
36
+ # Called if the WS-Call should be interrupted. The decision how to deal
37
+ # with this situation is given to the handler. To provide the possibility
38
+ # of a continue the Handler will be asked for a passthrough
39
+ def activity_stop
40
+ $long_track += "STOPPED #{@__myhandler_position}\n"
41
+ $short_track << "S#{@__myhandler_position}"
42
+ @t.exit if @t
43
+ @__myhandler_stopped = true
44
+ end
45
+ # is called from WEEL after stop_call to ask for a passthrough-value that may give
46
+ # information about how to continue the call. This passthrough-value is given
47
+ # to activity_handle if the workflow is configured to do so.
48
+ def activity_passthrough_value
49
+ "SOME passthrough"
50
+ end
51
+
52
+ # Called if the execution of the actual activity_handle is not necessary anymore
53
+ # It is definit that the call will not be continued.
54
+ # At this stage, this is only the case if parallel branches are not needed
55
+ # anymore to continue the workflow
56
+ def activity_no_longer_necessary
57
+ $long_track += "NO_LONGER_NECCESARY #{@__myhandler_position}\n"
58
+ $short_track << "NLN#{@__myhandler_position}"
59
+ @t.exit if @t
60
+ @__myhandler_returnValue = "No longer necessary"
61
+ @__myhandler_stopped = true
62
+ end
63
+ # Is called if a Activity is executed correctly
64
+ def inform_activity_manipulate
65
+ $long_track += "MANIPULATE #{@__myhandler_position}\n"
66
+ $short_track << "M#{@__myhandler_position}"
67
+ end
68
+ # Is called if a Activity is executed correctly
69
+ def inform_activity_done
70
+ $long_track += "DONE #{@__myhandler_position}\n"
71
+ $short_track << "D#{@__myhandler_position}"
72
+ end
73
+ # Is called if a Activity is executed with an error
74
+ def inform_activity_failed(err)
75
+ $long_track += "FAILED #{@__myhandler_position}: #{err}\n"
76
+ $short_track << "F#{@__myhandler_position}"
77
+ raise(err)
78
+ end
79
+ def inform_syntax_error(err,code)
80
+ $long_track += "ERROR: Syntax messed with error #{err}\n"
81
+ $short_track << "E"
82
+ raise(err)
83
+ end
84
+ def inform_state_change(newstate)
85
+ $long_track += "---> STATE #{newstate}\n"
86
+ $short_track << "|#{newstate}|"
87
+ end
88
+ end
89
+
90
+ module TestMixin #{{{
91
+ def setup
92
+ $long_track = ""
93
+ $short_track = ""
94
+ @wf = TestWorkflow.new
95
+ end
96
+
97
+ def teardown
98
+ @wf.stop.join
99
+ $long_track = ""
100
+ $short_track = ""
101
+ end
102
+
103
+ def wf_assert(what,cond=true)
104
+ if cond
105
+ assert($long_track.include?(what),"Missing \"#{what}\":\n#{$long_track}")
106
+ else
107
+ assert(!$long_track.include?(what),"Missing \"#{what}\":\n#{$long_track}")
108
+ end
109
+ end
110
+ def wf_sassert(what,cond=true)
111
+ if cond
112
+ assert($short_track.include?(what),"#{$short_track}\nNot Present \"#{what}\":\n#{$long_track}")
113
+ else
114
+ assert(!$short_track.include?(what),"#{$short_track}\nNot Present \"#{what}\":\n#{$long_track}")
115
+ end
116
+ end
117
+ def wf_rsassert(pat='')
118
+ assert($short_track =~ /#{pat}/,"Somehow executed different #{$short_track} should be '#{pat}'")
119
+ end
120
+ end #}}}
@@ -0,0 +1,35 @@
1
+ require File.expand_path(::File.dirname(__FILE__) + '/../lib/weel')
2
+ require File.expand_path(::File.dirname(__FILE__) + '/TestHandlerWrapper')
3
+
4
+ class TestWorkflow < WEEL
5
+ handlerwrapper TestHandlerWrapper
6
+
7
+ endpoint :endpoint1 => 'http://www.heise.de'
8
+ endpoint :stop => 'stop it'
9
+ data :x => 'begin_'
10
+
11
+ control flow do
12
+ activity :a1_1, :call, :endpoint1 do |result|
13
+ data.x += "#{result}"
14
+ end
15
+ parallel :wait => 2 do
16
+ parallel_branch do
17
+ activity :a2_1_1, :call, :endpoint1
18
+ end
19
+ parallel_branch do
20
+ activity :a2_2_1, :call, :endpoint1
21
+ end
22
+ end
23
+ activity :a3, :manipulate do
24
+ data.x += '_end'
25
+ end
26
+ choose do
27
+ alternative data.x != nil do
28
+ activity :a4a, :call, :endpoint1
29
+ end
30
+ otherwise do
31
+ activity :a4b, :call, :endpoint1
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,82 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestChoose < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_choose_alternative
8
+ @wf.description do
9
+ choose do
10
+ alternative true do
11
+ activity :a_1, :call, :endpoint1
12
+ end
13
+ alternative false do
14
+ activity :a_2, :call, :endpoint1
15
+ end
16
+ otherwise do
17
+ activity :a_3, :call, :endpoint1
18
+ end
19
+ end
20
+ end
21
+ @wf.start.join
22
+ wf_assert("CALL a_1: passthrough=[], endpoint=[http://www.heise.de], parameters=[{}]")
23
+ wf_assert("CALL a_2:",false)
24
+ wf_assert("CALL a_3:",false)
25
+ end
26
+
27
+ def test_choose_otherwise
28
+ @wf.description do
29
+ choose do
30
+ alternative false do
31
+ activity :a_1, :call, :endpoint1
32
+ end
33
+ otherwise do
34
+ activity :a_2, :call, :endpoint1
35
+ end
36
+ end
37
+ end
38
+ @wf.start.join
39
+ wf_assert("CALL a_2: passthrough=[], endpoint=[http://www.heise.de], parameters=[{}]")
40
+ wf_assert("CALL a_1:",false)
41
+ end
42
+
43
+ def test_choose_nested
44
+ @wf.description do
45
+ choose do
46
+ alternative true do
47
+ choose do
48
+ alternative false do
49
+ activity :a_1_1, :call, :endpoint1
50
+ end
51
+ alternative true do
52
+ choose do
53
+ alternative false do
54
+ activity :a_1_1_1, :call, :endpoint1
55
+ end
56
+ otherwise do
57
+ activity :a_1_1_2, :call, :endpoint1
58
+ end
59
+ end
60
+ end
61
+ otherwise do
62
+ activity :a_1_3, :call, :endpoint1
63
+ end
64
+ end
65
+ end
66
+ otherwise do
67
+ activity :a_2, :call, :endpoint1
68
+ end
69
+ end
70
+ end
71
+ @wf.start.join
72
+ wf_assert("CALL a_1_1_2: passthrough=[], endpoint=[http://www.heise.de], parameters=[{}]",true)
73
+ wf_assert("CALL a_1_1:",false)
74
+ wf_assert("CALL a_1_1_1:",false)
75
+ wf_assert("CALL a_1_3:",false)
76
+ wf_assert("CALL a_2:",false)
77
+ end
78
+
79
+ def test_choose_searchmode
80
+
81
+ end
82
+ end
@@ -0,0 +1,38 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestCodeReplace < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_replace
8
+ @wf.description do
9
+ activity :a_test_1_1, :call, :endpoint1
10
+ activity :a_test_1_2, :call, :endpoint1
11
+ activity :a_test_1_3, :call, :endpoint1
12
+ end
13
+ @wf.search WEEL::Position.new(:a_test_1_1, :at)
14
+ @wf.start.join
15
+ wf_assert("CALL a_test_1_1:")
16
+ wf_assert("CALL a_test_1_2:")
17
+ wf_assert("CALL a_test_1_3:")
18
+ wf_sassert("|running|Ca_test_1_1Da_test_1_1Ca_test_1_2Da_test_1_2Ca_test_1_3Da_test_1_3|finished|")
19
+ end
20
+ #def test_wfdescription_string
21
+ # ret = @wf.description "activity :b_test_1_1, :call, :endpoint1"
22
+ # @wf.search WEEL::Position.new(:b_test_1_1, :at)
23
+ # @wf.start.join
24
+ # wf_assert("DONE b_test_1_1")
25
+ # wf_sassert("|running|Cb_test_1_1Db_test_1_1|finished|")
26
+ #end
27
+ def test_wfdescription_block
28
+ ret = @wf.description do
29
+ activity :c_test_1_1, :call, :endpoint1
30
+ activity :c_test_1_2, :call, :endpoint1
31
+ end
32
+
33
+ assert(ret.class == Proc, "wf_description should be nil => not available. codeblock was given!")
34
+ @wf.search WEEL::Position.new(:c_test_1_2, :at)
35
+ @wf.start.join
36
+ wf_sassert("|running|Cc_test_1_2Dc_test_1_2|finished|")
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestData < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_check_data
8
+ data = @wf.data
9
+ assert(data.is_a?(Hash), "data is not a Hash")
10
+ assert(data.size == 1, "data has not exactly 1 element, it has #{data.size}")
11
+ assert(data.keys[0] == :x, "data.keys[0] has not the correct value [#{data.keys[0]}]")
12
+ assert(data[:x] == "begin_", "data[:x] has not the correct value")
13
+ end
14
+ def test_set_data_variable
15
+ @wf.data[:a] = "test1"
16
+ data = @wf.data
17
+ assert(data.is_a?(Hash), "data is not a Hash")
18
+ assert(data.keys.include?(:a), "data has no key :a")
19
+ assert(data[:a] == "test1", "data[:a] has not the correct value [#{data[:x]}]")
20
+ end
21
+ def test_set_data
22
+ @wf.data[:x] = "test1"
23
+ @wf.data[:y] = "test2"
24
+ data = @wf.data
25
+ assert(data.is_a?(Hash), "data is not a Hash")
26
+ assert(data.size == 2, "data has not exactly 1 element, it has #{data.size}")
27
+ assert(data.keys.include?(:x), "data has no key x")
28
+ assert(data.keys.include?(:y), "data has no key y")
29
+ assert(data[:x] == "test1", "data[:x] has not the correct value [#{data[:x]}]")
30
+ assert(data[:y] == "test2", "data[:y] has not the correct value [#{data[:y]}]")
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestEndpoint < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_check_endpoint
8
+ ep1 = @wf.endpoints[:endpoint1]
9
+ assert(ep1.is_a?(String), "Endpoint1 is no string but should be")
10
+ assert(ep1 == "http://www.heise.de", "Endpoint1 has wrong value [#{ep1}]")
11
+ end
12
+ def test_create_endpoint
13
+ @wf.endpoint :endpoint2 => "http://www.test.at"
14
+ ep2 = @wf.endpoints[:endpoint2]
15
+ assert(ep2.is_a?(String), "Endpoint1 is no string but should be")
16
+ assert(ep2 == "http://www.test.at", "Endpoint1 has wrong value [#{ep2}]")
17
+ end
18
+ def test_change_endpoint
19
+ @wf.endpoint :endpoint1 => "http://www.newpoint.com"
20
+ ep1 = @wf.endpoints[:endpoint1]
21
+ assert(ep1.is_a?(String), "Endpoint1 is no string but should be")
22
+ assert(ep1 == "http://www.newpoint.com", "Endpoint1 has wrong value [#{ep1}]")
23
+ end
24
+ def test_change_endpoint2
25
+ @wf.endpoints[:endpoint1] = "http://www.newpoint2.com"
26
+ ep1 = @wf.endpoints[:endpoint1]
27
+ assert(ep1.is_a?(String), "Endpoint1 is no string but should be")
28
+ assert(ep1 == "http://www.newpoint2.com", "Endpoint1 has wrong value [#{ep1}]")
29
+ end
30
+
31
+ def test_endpoints
32
+ @wf.endpoint :endpoint2 => "http://www.test.at" # asure that there is endpoint1 & endpoint2
33
+ @wf.endpoints[:endpoint1]="http://www.test2.com" # asure that ep1 has original value
34
+ eps = @wf.endpoints
35
+ assert(eps.is_a?(Hash), "Endpoints should result a Hash but returns a #{eps.class}")
36
+ assert(eps.size == 3, "Endpoints should have two entries: #{eps.inspect}")
37
+ assert(eps[:endpoint1] == "http://www.test2.com", "Endpoint 1 has wrong value or does not exist: #{eps.inspect}")
38
+ assert(eps[:endpoint2] == "http://www.test.at", "Endpoint 2 has wrong value or does not exist: #{eps.inspect}")
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestCaseHandler < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_handler
8
+ assert_raise RuntimeError do
9
+ @wf.handlerwrapper = String
10
+ end
11
+ assert_nothing_raised do
12
+ @wf.handlerwrapper = TestHandlerWrapper
13
+ end
14
+ end
15
+ def test_handlerargs
16
+ @wf.handlerwrapper_args = ["1", "2"]
17
+ assert(@wf.handlerwrapper_args.is_a?(Array), "Handler arguments is not an array, it is a #{@wf.handlerwrapper_args.inspect}")
18
+ end
19
+ end
@@ -0,0 +1,115 @@
1
+ require 'test/unit'
2
+ require File.expand_path(::File.dirname(__FILE__) + '/../TestWorkflow')
3
+
4
+ class TestParallel < Test::Unit::TestCase
5
+ include TestMixin
6
+
7
+ def test_parallel_simple
8
+ @wf.description do
9
+ parallel do
10
+ parallel_branch do
11
+ activity :a_1, :call, :endpoint1, :call => Proc.new{ sleep 0.5 }
12
+ end
13
+ parallel_branch do
14
+ activity :a_2, :call, :endpoint1, :call => Proc.new{ sleep 0.5 }
15
+ end
16
+ parallel_branch do
17
+ activity :a_3, :call, :endpoint1, :call => Proc.new{ sleep 0.5 }
18
+ end
19
+ end
20
+ end
21
+ wf = @wf.start
22
+ sleep(0.25)
23
+ wf_assert("CALL a_1:")
24
+ wf_assert("CALL a_2:")
25
+ wf_assert("CALL a_3:")
26
+ wf.join
27
+ wf_assert("DONE a_1")
28
+ wf_assert("DONE a_2")
29
+ wf_assert("DONE a_3")
30
+ end
31
+ def test_parallel_wait
32
+ @wf.description do
33
+ parallel :wait do
34
+ parallel_branch do
35
+ activity :a_1, :call, :endpoint1
36
+ end
37
+ parallel_branch do
38
+ activity :a_2, :call, :endpoint1, :call => Proc.new{ sleep 0.5 }
39
+ end
40
+ end
41
+ activity :a_3, :call, :endpoint1
42
+ end
43
+ @wf.start.join
44
+ wf_assert('CALL a_1')
45
+ wf_assert('DONE a_1')
46
+ wf_assert('CALL a_2')
47
+ wf_sassert('Da_2Ca_3Da_3|finished|')
48
+ end
49
+ def test_parallel_nowait
50
+ @wf.description do
51
+ parallel :wait => 1 do
52
+ parallel_branch do
53
+ activity :a_1, :call, :endpoint1
54
+ end
55
+ parallel_branch do
56
+ activity :a_2, :call, :endpoint1, :call => Proc.new{ sleep 8.5 }
57
+ end
58
+ end
59
+ activity :a_3, :call, :endpoint1
60
+ end
61
+ @wf.start.join
62
+ wf_assert('CALL a_1')
63
+ wf_assert('CALL a_2')
64
+ wf_sassert('NLNa_2Ca_3Da_3|finished|')
65
+ end
66
+ def test_parallel_no_longer_necessary
67
+ @wf.description do
68
+ parallel :wait => 1 do
69
+ parallel_branch do
70
+ activity :a_1, :call, :endpoint1
71
+ end
72
+ parallel_branch do
73
+ activity :a_2, :call, :endpoint1, :call => Proc.new{ sleep 0.5 }
74
+ activity :a_2_2, :call, :endpoint1
75
+ end
76
+ end
77
+ activity :a_3, :call, :endpoint1
78
+ end
79
+ @wf.start.join
80
+ wf_assert('CALL a_1')
81
+ wf_assert('CALL a_2')
82
+ wf_sassert('NLNa_2Ca_3Da_3|finished|')
83
+ end
84
+ def test_parallel_nested
85
+ # |- :a_1
86
+ # |-|-|- :a_2_1_1
87
+ # |-|-|- :a_2_1_2
88
+ # |-|-|- => :a_2_1_3
89
+ # |-|- :a_2_2
90
+ # |-|- :a_2_3
91
+ # |- => :a_3
92
+ @wf.description do
93
+ parallel :wait do
94
+ parallel_branch do activity :a_1, :call, :endpoint1 end
95
+ parallel_branch do
96
+ parallel :wait do
97
+ parallel_branch do
98
+ parallel :wait do
99
+ parallel_branch do activity :a_2_1_1, :call, :endpoint1, :call => Proc.new {sleep 0.2} end
100
+ parallel_branch do activity :a_2_1_2, :call, :endpoint1, :call => Proc.new {sleep 0.4} end
101
+ end
102
+ activity :a_2_1_3, :call, :endpoint1, :call => Proc.new {sleep 0.8}
103
+ end
104
+ parallel_branch do activity :a_2_2, :call, :endpoint1, :call => Proc.new {sleep 0.8} end
105
+ parallel_branch do activity :a_2_3, :call, :endpoint1, :call => Proc.new {sleep 1.0} end
106
+ end
107
+ end
108
+ end
109
+ activity :a_3, :call, :endpoint1
110
+ end
111
+ @wf.start.join
112
+ nump = $long_track.split("\n").delete_if{|e| !(e =~ /^(DONE)/)}
113
+ assert(nump == ["DONE a_1", "DONE a_2_1_1", "DONE a_2_1_2", "DONE a_2_2", "DONE a_2_3", "DONE a_2_1_3", "DONE a_3"], "not in the right order, sorry")
114
+ end
115
+ end