oflow 0.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.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +182 -0
- data/lib/oflow/actor.rb +76 -0
- data/lib/oflow/actors/errorhandler.rb +32 -0
- data/lib/oflow/actors/ignore.rb +22 -0
- data/lib/oflow/actors/log.rb +175 -0
- data/lib/oflow/actors/relay.rb +23 -0
- data/lib/oflow/actors/timer.rb +126 -0
- data/lib/oflow/actors.rb +11 -0
- data/lib/oflow/box.rb +195 -0
- data/lib/oflow/env.rb +52 -0
- data/lib/oflow/errors.rb +74 -0
- data/lib/oflow/flow.rb +75 -0
- data/lib/oflow/haserrorhandler.rb +48 -0
- data/lib/oflow/haslinks.rb +64 -0
- data/lib/oflow/haslog.rb +72 -0
- data/lib/oflow/hasname.rb +31 -0
- data/lib/oflow/hastasks.rb +209 -0
- data/lib/oflow/inspector.rb +501 -0
- data/lib/oflow/link.rb +43 -0
- data/lib/oflow/pattern.rb +8 -0
- data/lib/oflow/stamp.rb +39 -0
- data/lib/oflow/task.rb +415 -0
- data/lib/oflow/test/action.rb +21 -0
- data/lib/oflow/test/actorwrap.rb +62 -0
- data/lib/oflow/test.rb +8 -0
- data/lib/oflow/tracker.rb +109 -0
- data/lib/oflow/version.rb +5 -0
- data/lib/oflow.rb +23 -0
- data/test/actors/log_test.rb +57 -0
- data/test/actors/timer_test.rb +56 -0
- data/test/actorwrap_test.rb +48 -0
- data/test/all_tests.rb +27 -0
- data/test/box_test.rb +127 -0
- data/test/collector.rb +23 -0
- data/test/flow_basic_test.rb +93 -0
- data/test/flow_cfg_error_test.rb +94 -0
- data/test/flow_log_test.rb +87 -0
- data/test/flow_nest_test.rb +215 -0
- data/test/flow_rescue_test.rb +133 -0
- data/test/flow_tracker_test.rb +82 -0
- data/test/stutter.rb +21 -0
- data/test/task_test.rb +98 -0
- data/test/tracker_test.rb +59 -0
- metadata +93 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
[ File.dirname(__FILE__),
|
5
|
+
File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
].each { |path| $: << path unless $:.include?(path) }
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
require 'oflow'
|
10
|
+
|
11
|
+
require 'collector'
|
12
|
+
|
13
|
+
class Hop < ::OFlow::Actor
|
14
|
+
|
15
|
+
def initialize(task, options)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform(op, box)
|
20
|
+
task.info("#{op} #{box.contents}")
|
21
|
+
task.ship(op, box)
|
22
|
+
end
|
23
|
+
|
24
|
+
end # Hop
|
25
|
+
|
26
|
+
class FlowNestTest < ::Test::Unit::TestCase
|
27
|
+
|
28
|
+
def test_flow_nest
|
29
|
+
trigger = nil
|
30
|
+
collector = nil
|
31
|
+
::OFlow::Env.flow(:nest, :opt1 => 1) { |f|
|
32
|
+
# use collector as the log
|
33
|
+
f.task(:log, Collector) { |t|
|
34
|
+
collector = t.actor
|
35
|
+
}
|
36
|
+
|
37
|
+
# starts off the process
|
38
|
+
trigger = f.task(:trigger, Hop) { |t|
|
39
|
+
t.link(nil, :deep, nil)
|
40
|
+
}
|
41
|
+
# a nested flow
|
42
|
+
f.flow(:deep) { |f2|
|
43
|
+
f2.route(nil, :one, nil)
|
44
|
+
f2.task(:one, Hop) { |t|
|
45
|
+
t.link(nil, :two, nil)
|
46
|
+
}
|
47
|
+
f2.task(:two, Hop) { |t|
|
48
|
+
t.link(nil, :flow, :bye)
|
49
|
+
}
|
50
|
+
f2.link(:bye, :out, nil)
|
51
|
+
}
|
52
|
+
f.task(:out, Hop) { |t|
|
53
|
+
t.link(nil, :done, nil)
|
54
|
+
}
|
55
|
+
f.task(:done, ::OFlow::Actors::Ignore)
|
56
|
+
}
|
57
|
+
|
58
|
+
# see if the flow was constructed correctly
|
59
|
+
assert_equal(%|OFlow::Env {
|
60
|
+
nest (OFlow::Flow) {
|
61
|
+
log (Collector) {
|
62
|
+
}
|
63
|
+
trigger (Hop) {
|
64
|
+
=> deep:
|
65
|
+
}
|
66
|
+
deep (OFlow::Flow) {
|
67
|
+
one (Hop) {
|
68
|
+
=> two:
|
69
|
+
}
|
70
|
+
two (Hop) {
|
71
|
+
=> flow:bye
|
72
|
+
}
|
73
|
+
* one:
|
74
|
+
bye => out:
|
75
|
+
}
|
76
|
+
out (Hop) {
|
77
|
+
=> done:
|
78
|
+
}
|
79
|
+
done (OFlow::Actors::Ignore) {
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}|, ::OFlow::Env.describe())
|
83
|
+
|
84
|
+
# run it and check the output
|
85
|
+
trigger.receive(:go, ::OFlow::Box.new(7))
|
86
|
+
::OFlow::Env.flush()
|
87
|
+
assert_equal([['go 7', ':nest:trigger'],
|
88
|
+
[' 7', ':nest:deep:one'],
|
89
|
+
[' 7', ':nest:deep:two'],
|
90
|
+
[' 7', ':nest:out']
|
91
|
+
], collector.collection)
|
92
|
+
|
93
|
+
::OFlow::Env.clear()
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_flow_nest_deep
|
97
|
+
trigger = nil
|
98
|
+
collector = nil
|
99
|
+
::OFlow::Env.flow(:nest_deep, :opt1 => 1) { |f|
|
100
|
+
# use collector as the log
|
101
|
+
f.task(:log, Collector) { |t|
|
102
|
+
collector = t.actor
|
103
|
+
}
|
104
|
+
|
105
|
+
# starts off the process
|
106
|
+
trigger = f.task(:trigger, Hop) { |t|
|
107
|
+
t.link(nil, :deep, nil)
|
108
|
+
}
|
109
|
+
# a nested flow
|
110
|
+
f.flow(:deep) { |f2|
|
111
|
+
f2.route(nil, :deeper, nil)
|
112
|
+
f2.flow(:deeper) { |f3|
|
113
|
+
f3.route(nil, :one, nil)
|
114
|
+
f3.task(:one, Hop) { |t|
|
115
|
+
t.link(nil, :two, nil)
|
116
|
+
}
|
117
|
+
f3.task(:two, Hop) { |t|
|
118
|
+
t.link(nil, :flow, :bye)
|
119
|
+
}
|
120
|
+
f3.link(:bye, :flow, :bye)
|
121
|
+
}
|
122
|
+
f2.link(:bye, :out, nil)
|
123
|
+
}
|
124
|
+
f.task(:out, Hop) { |t|
|
125
|
+
t.link(nil, :done, nil)
|
126
|
+
}
|
127
|
+
f.task(:done, ::OFlow::Actors::Ignore)
|
128
|
+
}
|
129
|
+
|
130
|
+
# see if the flow was constructed correctly
|
131
|
+
assert_equal(%|OFlow::Env {
|
132
|
+
nest_deep (OFlow::Flow) {
|
133
|
+
log (Collector) {
|
134
|
+
}
|
135
|
+
trigger (Hop) {
|
136
|
+
=> deep:
|
137
|
+
}
|
138
|
+
deep (OFlow::Flow) {
|
139
|
+
deeper (OFlow::Flow) {
|
140
|
+
one (Hop) {
|
141
|
+
=> two:
|
142
|
+
}
|
143
|
+
two (Hop) {
|
144
|
+
=> flow:bye
|
145
|
+
}
|
146
|
+
* one:
|
147
|
+
bye => flow:bye
|
148
|
+
}
|
149
|
+
* deeper:
|
150
|
+
bye => out:
|
151
|
+
}
|
152
|
+
out (Hop) {
|
153
|
+
=> done:
|
154
|
+
}
|
155
|
+
done (OFlow::Actors::Ignore) {
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}|, ::OFlow::Env.describe())
|
159
|
+
|
160
|
+
# run it and check the output
|
161
|
+
trigger.receive(:go, ::OFlow::Box.new(7))
|
162
|
+
::OFlow::Env.flush()
|
163
|
+
assert_equal([['go 7', ':nest_deep:trigger'],
|
164
|
+
[' 7', ':nest_deep:deep:deeper:one'],
|
165
|
+
[' 7', ':nest_deep:deep:deeper:two'],
|
166
|
+
[' 7', ':nest_deep:out']
|
167
|
+
], collector.collection)
|
168
|
+
|
169
|
+
::OFlow::Env.clear()
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_flow_nest_label
|
173
|
+
trigger = nil
|
174
|
+
collector = nil
|
175
|
+
::OFlow::Env.flow(:nest) { |f|
|
176
|
+
# use collector as the log
|
177
|
+
f.task(:log, Collector) { |t|
|
178
|
+
collector = t.actor
|
179
|
+
}
|
180
|
+
|
181
|
+
# starts off the process
|
182
|
+
trigger = f.task(:trigger, Hop) { |t|
|
183
|
+
t.link(:go, :deep, :first)
|
184
|
+
}
|
185
|
+
# a nested flow
|
186
|
+
f.flow(:deep) { |f2|
|
187
|
+
f2.route(:first, :one, :hip)
|
188
|
+
f2.task(:one, Hop) { |t|
|
189
|
+
t.link(:hip, :two, :hop)
|
190
|
+
}
|
191
|
+
f2.task(:two, Hop) { |t|
|
192
|
+
t.link(:hop, :flow, :get_out)
|
193
|
+
}
|
194
|
+
f2.link(:get_out, :out, :finish)
|
195
|
+
}
|
196
|
+
f.task(:out, Hop) { |t|
|
197
|
+
t.link(:finish, :done, nil)
|
198
|
+
}
|
199
|
+
f.task(:done, ::OFlow::Actors::Ignore)
|
200
|
+
}
|
201
|
+
|
202
|
+
# run it and check the output
|
203
|
+
trigger.receive(:go, ::OFlow::Box.new(7))
|
204
|
+
::OFlow::Env.flush()
|
205
|
+
assert_equal([['go 7', ':nest:trigger'],
|
206
|
+
['hip 7', ':nest:deep:one'],
|
207
|
+
['hop 7', ':nest:deep:two'],
|
208
|
+
['finish 7', ':nest:out']
|
209
|
+
], collector.collection)
|
210
|
+
|
211
|
+
::OFlow::Env.clear()
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
end # FlowNestTest
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
[ File.dirname(__FILE__),
|
5
|
+
File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
].each { |path| $: << path unless $:.include?(path) }
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
require 'oflow'
|
10
|
+
|
11
|
+
require 'collector'
|
12
|
+
|
13
|
+
class Crash < ::OFlow::Actor
|
14
|
+
def initialize(task, options)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform(op, box)
|
19
|
+
nil.crash()
|
20
|
+
end
|
21
|
+
|
22
|
+
end # Crash
|
23
|
+
|
24
|
+
class FlowRescueTest < ::Test::Unit::TestCase
|
25
|
+
|
26
|
+
# Make sure the error handler works and forwards to the 'error' task if it
|
27
|
+
# exists.
|
28
|
+
def test_flow_rescue_task
|
29
|
+
trigger = nil
|
30
|
+
collector = nil
|
31
|
+
::OFlow::Env.flow('rescue') { |f|
|
32
|
+
trigger = f.task('crash', Crash)
|
33
|
+
f.task(:collector, Collector) { |t|
|
34
|
+
collector = t.actor
|
35
|
+
}
|
36
|
+
f.task(:error, ::OFlow::Actors::Relay) { |t|
|
37
|
+
t.link(nil, 'collector', 'error')
|
38
|
+
}
|
39
|
+
f.task(:log, ::OFlow::Actors::Relay) { |t|
|
40
|
+
t.link(nil, 'collector', 'log')
|
41
|
+
}
|
42
|
+
}
|
43
|
+
trigger.receive(:knock, ::OFlow::Box.new(7))
|
44
|
+
::OFlow::Env.flush()
|
45
|
+
|
46
|
+
assert_equal(collector.collection.size, 1)
|
47
|
+
assert_equal(collector.collection[0][0].class, NoMethodError)
|
48
|
+
assert_equal(collector.collection[0][1], ':rescue:crash')
|
49
|
+
|
50
|
+
::OFlow::Env.clear()
|
51
|
+
end
|
52
|
+
|
53
|
+
# Make sure the error handler on the flow is used to handle errors.
|
54
|
+
def test_flow_rescue_var
|
55
|
+
trigger = nil
|
56
|
+
collector = nil
|
57
|
+
::OFlow::Env.flow('rescue') { |f|
|
58
|
+
trigger = f.task('crash', Crash)
|
59
|
+
f.error_handler = f.task(:collector, Collector) { |t|
|
60
|
+
collector = t.actor
|
61
|
+
}
|
62
|
+
f.task(:log, ::OFlow::Actors::Relay) { |t|
|
63
|
+
t.link(nil, 'collector', 'log')
|
64
|
+
}
|
65
|
+
}
|
66
|
+
trigger.receive(:knock, ::OFlow::Box.new(7))
|
67
|
+
::OFlow::Env.flush()
|
68
|
+
|
69
|
+
assert_equal(collector.collection.size, 1)
|
70
|
+
assert_equal(collector.collection[0][0].class, NoMethodError)
|
71
|
+
assert_equal(collector.collection[0][1], ':rescue:crash')
|
72
|
+
|
73
|
+
::OFlow::Env.clear()
|
74
|
+
end
|
75
|
+
|
76
|
+
# Make sure the error handler on the flow is used to handle errors.
|
77
|
+
def test_flow_rescue_env
|
78
|
+
trigger = nil
|
79
|
+
collector = nil
|
80
|
+
::OFlow::Env.flow('rescue') { |f|
|
81
|
+
trigger = f.task('crash', Crash)
|
82
|
+
::OFlow::Env.error_handler = f.task(:collector, Collector) { |t|
|
83
|
+
collector = t.actor
|
84
|
+
}
|
85
|
+
f.task(:log, ::OFlow::Actors::Relay) { |t|
|
86
|
+
t.link(nil, 'collector', 'log')
|
87
|
+
}
|
88
|
+
}
|
89
|
+
trigger.receive(:knock, ::OFlow::Box.new(7))
|
90
|
+
::OFlow::Env.flush()
|
91
|
+
|
92
|
+
assert_equal(1, collector.collection.size)
|
93
|
+
assert_equal(NoMethodError, collector.collection[0][0].class)
|
94
|
+
assert_equal(':rescue:crash', collector.collection[0][1])
|
95
|
+
|
96
|
+
::OFlow::Env.clear()
|
97
|
+
end
|
98
|
+
|
99
|
+
# Make sure the default error handler on the flow passes a message to the log.
|
100
|
+
def test_flow_rescue_env_log
|
101
|
+
trigger = nil
|
102
|
+
collector = nil
|
103
|
+
::OFlow::Env.flow('rescue') { |f|
|
104
|
+
trigger = f.task('crash', Crash)
|
105
|
+
::OFlow::Env.log = f.task(:collector, Collector) { |t|
|
106
|
+
collector = t.actor
|
107
|
+
}
|
108
|
+
}
|
109
|
+
trigger.receive(:knock, ::OFlow::Box.new(7))
|
110
|
+
::OFlow::Env.flush()
|
111
|
+
|
112
|
+
assert_equal(1, collector.collection.size)
|
113
|
+
assert_equal(["NoMethodError: undefined method `crash' for nil:NilClass",
|
114
|
+
"/flow_rescue_test.rb:0:in `perform'",
|
115
|
+
"/task.rb:0:in `block in initialize'"],
|
116
|
+
simplify(collector.collection[0][0]))
|
117
|
+
|
118
|
+
assert_equal(':rescue:crash', collector.collection[0][1])
|
119
|
+
|
120
|
+
::OFlow::Env.clear()
|
121
|
+
end
|
122
|
+
|
123
|
+
def simplify(bt)
|
124
|
+
bt.split("\n").map do |line|
|
125
|
+
i = line.index(/\/\w+\.rb\:\d+/)
|
126
|
+
unless i.nil?
|
127
|
+
line = line[i..-1]
|
128
|
+
end
|
129
|
+
line.gsub(/\d+/, '0')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end # FlowRescueTest
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
[ File.dirname(__FILE__),
|
5
|
+
File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
].each { |path| $: << path unless $:.include?(path) }
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
require 'oflow'
|
10
|
+
|
11
|
+
require 'collector'
|
12
|
+
|
13
|
+
class Throw < ::OFlow::Actor
|
14
|
+
|
15
|
+
def initialize(task, options)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform(op, box)
|
20
|
+
task.ship(op, box)
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Throw
|
24
|
+
|
25
|
+
class Catch < ::OFlow::Actor
|
26
|
+
attr_reader :ball
|
27
|
+
|
28
|
+
def initialize(task, options)
|
29
|
+
super
|
30
|
+
@ball = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def perform(op, box)
|
34
|
+
@ball = box
|
35
|
+
end
|
36
|
+
|
37
|
+
end # Catch
|
38
|
+
|
39
|
+
class FlowTrackerTest < ::Test::Unit::TestCase
|
40
|
+
|
41
|
+
def test_flow_tracker
|
42
|
+
trigger = nil
|
43
|
+
catcher = nil
|
44
|
+
::OFlow::Env.flow(:nest, :opt1 => 1) { |f|
|
45
|
+
|
46
|
+
# starts off the process
|
47
|
+
trigger = f.task(:trigger, Throw) { |t|
|
48
|
+
t.link(nil, :deep, nil)
|
49
|
+
}
|
50
|
+
# a nested flow
|
51
|
+
f.flow(:deep) { |f2|
|
52
|
+
f2.route(nil, :one, nil)
|
53
|
+
f2.task(:one, Throw) { |t|
|
54
|
+
t.link(nil, :two, nil)
|
55
|
+
}
|
56
|
+
f2.task(:two, Throw) { |t|
|
57
|
+
t.link(nil, :flow, :bye)
|
58
|
+
}
|
59
|
+
f2.link(:bye, :out, nil)
|
60
|
+
}
|
61
|
+
f.task(:out, Throw) { |t|
|
62
|
+
t.link(nil, :done, nil)
|
63
|
+
}
|
64
|
+
catcher = f.task(:done, Catch)
|
65
|
+
}
|
66
|
+
|
67
|
+
# run it and check the output
|
68
|
+
trigger.receive(:go, ::OFlow::Box.new(7, ::OFlow::Tracker.create('test')))
|
69
|
+
::OFlow::Env.flush()
|
70
|
+
assert_equal(["test-",
|
71
|
+
":nest:trigger-go",
|
72
|
+
":nest:deep-",
|
73
|
+
":nest:deep:one-",
|
74
|
+
":nest:deep:two-",
|
75
|
+
":nest:deep-bye",
|
76
|
+
":nest:out-",
|
77
|
+
":nest:done-"], catcher.actor.ball.tracker.track.map {|s| s.where })
|
78
|
+
|
79
|
+
::OFlow::Env.clear()
|
80
|
+
end
|
81
|
+
|
82
|
+
end # FlowTrackerTest
|
data/test/stutter.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
[ File.dirname(__FILE__),
|
5
|
+
File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
].each { |path| $: << path unless $:.include?(path) }
|
7
|
+
|
8
|
+
require 'oflow'
|
9
|
+
|
10
|
+
class Stutter < ::OFlow::Actor
|
11
|
+
|
12
|
+
def initialize(task, options)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def perform(op, box)
|
17
|
+
task.ship(:collector, ::OFlow::Box.new([task.full_name, op, box.contents]))
|
18
|
+
task.ship(op, box)
|
19
|
+
end
|
20
|
+
|
21
|
+
end # Stutter
|
data/test/task_test.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
[ File.dirname(__FILE__),
|
5
|
+
File.join(File.dirname(__FILE__), "../lib")
|
6
|
+
].each { |path| $: << path unless $:.include?(path) }
|
7
|
+
|
8
|
+
require 'test/unit'
|
9
|
+
require 'oflow'
|
10
|
+
|
11
|
+
class Gather < ::OFlow::Actor
|
12
|
+
attr_accessor :requests
|
13
|
+
|
14
|
+
def initialize(task, options)
|
15
|
+
super
|
16
|
+
@requests = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform(op, box)
|
20
|
+
if @requests[op].nil?
|
21
|
+
@requests[op] = [box]
|
22
|
+
else
|
23
|
+
@requests[op] << box
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end # Gather
|
28
|
+
|
29
|
+
|
30
|
+
class TaskTest < ::Test::Unit::TestCase
|
31
|
+
|
32
|
+
def test_task_queue_count
|
33
|
+
task = ::OFlow::Task.new(nil, 'test', Gather)
|
34
|
+
assert_equal(0, task.queue_count())
|
35
|
+
task.stop()
|
36
|
+
task.receive(:dance, ::OFlow::Box.new('two step'))
|
37
|
+
assert_equal(1, task.queue_count())
|
38
|
+
task.receive(:dance, ::OFlow::Box.new('twist'))
|
39
|
+
assert_equal(2, task.queue_count())
|
40
|
+
task.shutdown()
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_task_perform
|
44
|
+
task = ::OFlow::Task.new(nil, 'test', Gather)
|
45
|
+
task.receive(:dance, ::OFlow::Box.new('two step'))
|
46
|
+
task.flush()
|
47
|
+
|
48
|
+
requests = task.actor.requests
|
49
|
+
assert_equal(1, requests.size)
|
50
|
+
boxes = requests[:dance]
|
51
|
+
assert_equal(1, boxes.size)
|
52
|
+
box = boxes[0]
|
53
|
+
assert_equal(false, box.nil?)
|
54
|
+
assert_equal('two step', box.contents)
|
55
|
+
task.shutdown()
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_task_perform_shutdown
|
59
|
+
task = ::OFlow::Task.new(nil, 'test', Gather)
|
60
|
+
task.receive(:dance, ::OFlow::Box.new('two step'))
|
61
|
+
task.shutdown(true)
|
62
|
+
|
63
|
+
requests = task.actor.requests
|
64
|
+
assert_equal(1, requests.size)
|
65
|
+
boxes = requests[:dance]
|
66
|
+
assert_equal(1, boxes.size)
|
67
|
+
box = boxes[0]
|
68
|
+
assert_equal(false, box.nil?)
|
69
|
+
assert_equal('two step', box.contents)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_task_raise_after_close
|
73
|
+
task = ::OFlow::Task.new(nil, 'test', Gather)
|
74
|
+
task.shutdown()
|
75
|
+
assert_raise(ThreadError) { task.start() }
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_task_max_queue_count
|
79
|
+
task = ::OFlow::Task.new(nil, 'test', Gather, :max_queue_count => 4, :req_timeout => 0.1)
|
80
|
+
task.stop()
|
81
|
+
6.times do |i|
|
82
|
+
begin
|
83
|
+
task.receive(:dance, ::OFlow::Box.new(i))
|
84
|
+
rescue ::OFlow::BusyError
|
85
|
+
# expected for all over first 4
|
86
|
+
end
|
87
|
+
end
|
88
|
+
task.start()
|
89
|
+
task.shutdown(true)
|
90
|
+
|
91
|
+
requests = task.actor.requests
|
92
|
+
boxes = requests[:dance]
|
93
|
+
assert_equal(4, boxes.size)
|
94
|
+
nums = boxes.map { |box| box.contents }
|
95
|
+
assert_equal([0, 1, 2, 3], nums)
|
96
|
+
end
|
97
|
+
|
98
|
+
end # TaskTest
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
# Ubuntu does not accept arguments to ruby when called using env. To get warnings to show up the -w options is
|
5
|
+
# required. That can be set in the RUBYOPT environment variable.
|
6
|
+
# export RUBYOPT=-w
|
7
|
+
|
8
|
+
$VERBOSE = true
|
9
|
+
|
10
|
+
$: << File.join(File.dirname(__FILE__), "../lib")
|
11
|
+
|
12
|
+
require 'test/unit'
|
13
|
+
require 'oflow'
|
14
|
+
|
15
|
+
class TrackerTest < ::Test::Unit::TestCase
|
16
|
+
|
17
|
+
def test_tracker_new
|
18
|
+
t = ::OFlow::Tracker.create('here')
|
19
|
+
t2 = ::OFlow::Tracker.create('here')
|
20
|
+
|
21
|
+
assert_not_equal(t.id, t2.id, 'id must be unique')
|
22
|
+
assert_equal('here', t.track[0].location)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_tracker_track
|
26
|
+
t = ::OFlow::Tracker.create('here')
|
27
|
+
t2 = t.receive('there', 'op1')
|
28
|
+
|
29
|
+
assert_equal('here', t.track[0].location)
|
30
|
+
assert_equal('here', t2.track[0].location)
|
31
|
+
assert_equal('there', t2.track[1].location)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_tracker_merge
|
35
|
+
t = ::OFlow::Tracker.create('here')
|
36
|
+
# 2 different paths
|
37
|
+
t2 = t.receive('there', 'op1')
|
38
|
+
t3 = t.receive('everywhere', 'op2')
|
39
|
+
# should not happen but should handle merging when not back to a common place
|
40
|
+
t4 = t2.merge(t3)
|
41
|
+
assert_equal('here', t4.track[0].location)
|
42
|
+
assert_equal(true, t4.track[1].is_a?(Array))
|
43
|
+
assert_equal(2, t4.track[1].size)
|
44
|
+
assert_equal('there', t4.track[1][0][0].location)
|
45
|
+
assert_equal('everywhere', t4.track[1][1][0].location)
|
46
|
+
|
47
|
+
# back to a common location
|
48
|
+
t2 = t2.receive('home', 'op1')
|
49
|
+
t3 = t3.receive('home', 'op1')
|
50
|
+
t4 = t2.merge(t3)
|
51
|
+
assert_equal('here', t4.track[0].location)
|
52
|
+
assert_equal(true, t4.track[1].is_a?(Array))
|
53
|
+
assert_equal(2, t4.track[1].size)
|
54
|
+
assert_equal('there', t4.track[1][0][0].location)
|
55
|
+
assert_equal('everywhere', t4.track[1][1][0].location)
|
56
|
+
assert_equal('home', t4.track[2].location)
|
57
|
+
end
|
58
|
+
|
59
|
+
end # TrackerTest
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oflow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Ohler
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Operations Workflow in Ruby. This implements a workflow/process flow
|
14
|
+
using multiple task nodes that each have their own queues and execution thread.
|
15
|
+
email: peter@ohler.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files:
|
19
|
+
- README.md
|
20
|
+
files:
|
21
|
+
- LICENSE
|
22
|
+
- README.md
|
23
|
+
- lib/oflow.rb
|
24
|
+
- lib/oflow/actor.rb
|
25
|
+
- lib/oflow/actors.rb
|
26
|
+
- lib/oflow/actors/errorhandler.rb
|
27
|
+
- lib/oflow/actors/ignore.rb
|
28
|
+
- lib/oflow/actors/log.rb
|
29
|
+
- lib/oflow/actors/relay.rb
|
30
|
+
- lib/oflow/actors/timer.rb
|
31
|
+
- lib/oflow/box.rb
|
32
|
+
- lib/oflow/env.rb
|
33
|
+
- lib/oflow/errors.rb
|
34
|
+
- lib/oflow/flow.rb
|
35
|
+
- lib/oflow/haserrorhandler.rb
|
36
|
+
- lib/oflow/haslinks.rb
|
37
|
+
- lib/oflow/haslog.rb
|
38
|
+
- lib/oflow/hasname.rb
|
39
|
+
- lib/oflow/hastasks.rb
|
40
|
+
- lib/oflow/inspector.rb
|
41
|
+
- lib/oflow/link.rb
|
42
|
+
- lib/oflow/pattern.rb
|
43
|
+
- lib/oflow/stamp.rb
|
44
|
+
- lib/oflow/task.rb
|
45
|
+
- lib/oflow/test.rb
|
46
|
+
- lib/oflow/test/action.rb
|
47
|
+
- lib/oflow/test/actorwrap.rb
|
48
|
+
- lib/oflow/tracker.rb
|
49
|
+
- lib/oflow/version.rb
|
50
|
+
- test/actors/log_test.rb
|
51
|
+
- test/actors/timer_test.rb
|
52
|
+
- test/actorwrap_test.rb
|
53
|
+
- test/all_tests.rb
|
54
|
+
- test/box_test.rb
|
55
|
+
- test/collector.rb
|
56
|
+
- test/flow_basic_test.rb
|
57
|
+
- test/flow_cfg_error_test.rb
|
58
|
+
- test/flow_log_test.rb
|
59
|
+
- test/flow_nest_test.rb
|
60
|
+
- test/flow_rescue_test.rb
|
61
|
+
- test/flow_tracker_test.rb
|
62
|
+
- test/stutter.rb
|
63
|
+
- test/task_test.rb
|
64
|
+
- test/tracker_test.rb
|
65
|
+
homepage: http://www.ohler.com/oflow
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
- GPL-3.0
|
69
|
+
metadata: {}
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options:
|
72
|
+
- "--main"
|
73
|
+
- README.md
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project: oflow
|
88
|
+
rubygems_version: 2.2.0
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Operations Workflow in Ruby
|
92
|
+
test_files: []
|
93
|
+
has_rdoc: true
|