scout-gear 8.0.0 → 8.1.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 +4 -4
- data/.vimproject +26 -9
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/bin/scout +15 -4
- data/doc/lib/scout/path.md +35 -0
- data/doc/lib/scout/workflow/task.md +13 -0
- data/lib/scout/cmd.rb +23 -24
- data/lib/scout/concurrent_stream.rb +36 -19
- data/lib/scout/exceptions.rb +10 -0
- data/lib/scout/log/color.rb +11 -11
- data/lib/scout/log/progress/report.rb +7 -5
- data/lib/scout/log/progress/util.rb +3 -0
- data/lib/scout/log/trap.rb +3 -3
- data/lib/scout/log.rb +64 -36
- data/lib/scout/meta_extension.rb +34 -0
- data/lib/scout/misc/digest.rb +11 -2
- data/lib/scout/misc/format.rb +12 -7
- data/lib/scout/misc/monitor.rb +11 -0
- data/lib/scout/misc/system.rb +48 -0
- data/lib/scout/named_array.rb +8 -0
- data/lib/scout/offsite/ssh.rb +171 -0
- data/lib/scout/offsite/step.rb +83 -0
- data/lib/scout/offsite/sync.rb +55 -0
- data/lib/scout/offsite.rb +3 -0
- data/lib/scout/open/lock.rb +5 -24
- data/lib/scout/open/remote.rb +12 -1
- data/lib/scout/open/stream.rb +110 -122
- data/lib/scout/open/util.rb +9 -0
- data/lib/scout/open.rb +5 -4
- data/lib/scout/path/find.rb +15 -10
- data/lib/scout/path/util.rb +5 -0
- data/lib/scout/persist/serialize.rb +3 -3
- data/lib/scout/persist.rb +1 -1
- data/lib/scout/resource/path.rb +4 -0
- data/lib/scout/resource/util.rb +10 -4
- data/lib/scout/tsv/dumper.rb +2 -0
- data/lib/scout/tsv/index.rb +28 -86
- data/lib/scout/tsv/open.rb +35 -14
- data/lib/scout/tsv/parser.rb +9 -2
- data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
- data/lib/scout/tsv/stream.rb +204 -0
- data/lib/scout/tsv/transformer.rb +11 -0
- data/lib/scout/tsv.rb +9 -2
- data/lib/scout/work_queue/worker.rb +2 -2
- data/lib/scout/work_queue.rb +36 -12
- data/lib/scout/workflow/definition.rb +2 -1
- data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
- data/lib/scout/workflow/deployment.rb +1 -0
- data/lib/scout/workflow/step/dependencies.rb +37 -11
- data/lib/scout/workflow/step/file.rb +5 -0
- data/lib/scout/workflow/step/info.rb +5 -3
- data/lib/scout/workflow/step/load.rb +1 -1
- data/lib/scout/workflow/step/provenance.rb +1 -0
- data/lib/scout/workflow/step/status.rb +6 -8
- data/lib/scout/workflow/step.rb +75 -30
- data/lib/scout/workflow/task/dependencies.rb +114 -0
- data/lib/scout/workflow/task/inputs.rb +27 -13
- data/lib/scout/workflow/task.rb +9 -108
- data/lib/scout/workflow/usage.rb +40 -12
- data/lib/scout/workflow.rb +4 -2
- data/lib/scout-gear.rb +2 -0
- data/lib/scout.rb +6 -0
- data/scout-gear.gemspec +32 -7
- data/scout_commands/doc +37 -0
- data/scout_commands/find +1 -0
- data/scout_commands/offsite +30 -0
- data/scout_commands/update +29 -0
- data/scout_commands/workflow/info +15 -3
- data/scout_commands/workflow/install +102 -0
- data/scout_commands/workflow/task +26 -5
- data/test/scout/offsite/test_ssh.rb +15 -0
- data/test/scout/offsite/test_step.rb +33 -0
- data/test/scout/offsite/test_sync.rb +36 -0
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/resource/test_path.rb +6 -0
- data/test/scout/test_named_array.rb +6 -0
- data/test/scout/test_persist.rb +3 -2
- data/test/scout/test_tsv.rb +17 -0
- data/test/scout/test_work_queue.rb +63 -41
- data/test/scout/tsv/persist/test_adapter.rb +1 -1
- data/test/scout/tsv/test_index.rb +14 -0
- data/test/scout/tsv/test_parser.rb +14 -0
- data/test/scout/tsv/test_stream.rb +200 -0
- data/test/scout/tsv/test_transformer.rb +12 -0
- data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
- data/test/scout/workflow/step/test_dependencies.rb +68 -0
- data/test/scout/workflow/step/test_info.rb +18 -0
- data/test/scout/workflow/step/test_status.rb +0 -1
- data/test/scout/workflow/task/test_dependencies.rb +355 -0
- data/test/scout/workflow/task/test_inputs.rb +53 -0
- data/test/scout/workflow/test_definition.rb +18 -0
- data/test/scout/workflow/test_documentation.rb +24 -0
- data/test/scout/workflow/test_step.rb +109 -0
- data/test/scout/workflow/test_task.rb +0 -287
- data/test/test_scout.rb +9 -0
- metadata +83 -5
- data/scout_commands/workflow/task_old +0 -706
@@ -21,5 +21,73 @@ class TestStepDependencies < Test::Unit::TestCase
|
|
21
21
|
assert_equal 2, step2.inputs[:input2]
|
22
22
|
assert_equal "12", step2.recursive_inputs[:input1]
|
23
23
|
end
|
24
|
+
|
25
|
+
def test_can_fail
|
26
|
+
tmpfile = tmpdir.test_step
|
27
|
+
step1 = Step.new tmpfile.step1, NamedArray.setup(["12"], %w(input1)) do |s|
|
28
|
+
raise ScoutException
|
29
|
+
end
|
30
|
+
|
31
|
+
step2 = Step.new tmpfile.step2, NamedArray.setup([2], %w(input2)) do |times|
|
32
|
+
step1 = dependencies.first
|
33
|
+
if step1.error?
|
34
|
+
(step1.inputs.first + " has unknown characters") * times
|
35
|
+
else
|
36
|
+
(step1.inputs.first + " has " + step1.load.to_s + " characters") * times
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
step2.dependencies = [step1]
|
41
|
+
step2.compute = {step1.path => [:canfail] }
|
42
|
+
|
43
|
+
assert_include step2.run, "unknown"
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_can_stream
|
47
|
+
tmpfile = tmpdir.test_step
|
48
|
+
|
49
|
+
Misc.with_env "SCOUT_EXPLICIT_STREAMING", "true" do
|
50
|
+
times = 10_000
|
51
|
+
sleep = 1 / times
|
52
|
+
|
53
|
+
step1 = Step.new tmpfile.step1, [times, sleep] do |times,sleep|
|
54
|
+
Open.open_pipe do |sin|
|
55
|
+
times.times do |i|
|
56
|
+
sin.puts "line-#{i}"
|
57
|
+
sleep sleep
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
step1.type = :array
|
62
|
+
|
63
|
+
step2 = Step.new tmpfile.step2 do
|
64
|
+
step1 = dependencies.first
|
65
|
+
raise ScoutException unless step1.streaming?
|
66
|
+
stream = step1.stream
|
67
|
+
|
68
|
+
Open.open_pipe do |sin|
|
69
|
+
while line = stream.gets
|
70
|
+
num = line.split("-").last
|
71
|
+
next if num.to_i % 2 == 1
|
72
|
+
sin.puts line
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
step2.type = :array
|
77
|
+
step2.dependencies = [step1]
|
78
|
+
|
79
|
+
assert_raise ScoutException do
|
80
|
+
step2.run
|
81
|
+
end
|
82
|
+
|
83
|
+
step2.recursive_clean
|
84
|
+
|
85
|
+
step2.compute = {step1.path => [:stream]}
|
86
|
+
|
87
|
+
assert_nothing_raised do
|
88
|
+
step2.run
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
24
92
|
end
|
25
93
|
|
@@ -25,4 +25,22 @@ class TestStepInfo < Test::Unit::TestCase
|
|
25
25
|
assert_equal "12 has 2 characters", step2.run
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
def test_inputs_marshal
|
30
|
+
TmpFile.with_file do |tmpdir|
|
31
|
+
Path.setup(tmpdir)
|
32
|
+
tmpfile = tmpdir.test_step
|
33
|
+
|
34
|
+
path = tmpfile.foo
|
35
|
+
step1 = Step.new tmpfile.step1, [path] do |s|
|
36
|
+
s.length
|
37
|
+
end
|
38
|
+
|
39
|
+
step1.run
|
40
|
+
|
41
|
+
refute Path === step1.info[:inputs][0]
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
28
46
|
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
require 'scout/workflow'
|
5
|
+
class TestTaskDependencies < Test::Unit::TestCase
|
6
|
+
def test_task_override_dep_exec
|
7
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
8
|
+
input :input1, :integer
|
9
|
+
task :step1 => :integer do |i| i end
|
10
|
+
|
11
|
+
dep :step1
|
12
|
+
input :input2, :integer, "Integer", 3
|
13
|
+
task :step2 => :integer do |i| i * step(:step1).load end
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_equal 6, wf.job(:step2, :input1 => 2, :input2 => 3).exec
|
17
|
+
|
18
|
+
step1_job = wf.job(:step1, :input1 => 6)
|
19
|
+
assert_equal 18, wf.job(:step2, :input1 => 2, "TaskInputs#step1" => step1_job).exec
|
20
|
+
|
21
|
+
assert_equal 18, wf.job(:step2, :input1 => 2, "TaskInputs#step1" => step1_job).exec
|
22
|
+
|
23
|
+
assert_equal 18, wf.job(:step2, "TaskInputs#step1" => step1_job).exec
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_task_override_dep
|
27
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
28
|
+
input :input1, :integer
|
29
|
+
task :step1 => :integer do |i| i end
|
30
|
+
|
31
|
+
dep :step1
|
32
|
+
input :input2, :integer, "Integer", 3
|
33
|
+
task :step2 => :integer do |i| i * step(:step1).load end
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_equal 6, wf.job(:step2, :input1 => 2, :input2 => 3).run
|
37
|
+
|
38
|
+
step1_job = wf.job(:step1, :input1 => 6)
|
39
|
+
assert_equal 18, wf.job(:step2, :input1 => 2, "TaskInputs#step1" => step1_job).run
|
40
|
+
|
41
|
+
assert_equal 18, wf.job(:step2, :input1 => 2, "TaskInputs#step1" => step1_job).run
|
42
|
+
|
43
|
+
assert_equal 18, wf.job(:step2, "TaskInputs#step1" => step1_job).run
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_input_dep
|
47
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
48
|
+
input :v1, :integer
|
49
|
+
input :v2, :integer
|
50
|
+
task :sum => :integer do |v1,v2|
|
51
|
+
v1 + v2
|
52
|
+
end
|
53
|
+
|
54
|
+
input :input1, :integer
|
55
|
+
task :step1 => :integer do |i| i end
|
56
|
+
|
57
|
+
input :input2, :integer
|
58
|
+
task :step2 => :integer do |i| i end
|
59
|
+
|
60
|
+
dep :step1, :input1 => 2
|
61
|
+
dep :step2, :input2 => 3
|
62
|
+
dep :sum, :v1 => :step1, :v2 => :step2
|
63
|
+
task :my_sum => :integer do
|
64
|
+
dependencies.last.load
|
65
|
+
end
|
66
|
+
|
67
|
+
dep :my_sum
|
68
|
+
task :double => :integer do
|
69
|
+
step(:my_sum).load * 2
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
job = wf.job(:my_sum)
|
74
|
+
assert_equal 5, job.run
|
75
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
76
|
+
|
77
|
+
job = wf.job(:double)
|
78
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
79
|
+
|
80
|
+
step1 = wf.job(:step1, :input1 => 3)
|
81
|
+
assert_equal 3, step1.run
|
82
|
+
job = wf.job(:double, "TaskInputs#step1" => step1)
|
83
|
+
assert_equal 12, job.run
|
84
|
+
assert_not_equal Task::DEFAULT_NAME, job.name
|
85
|
+
|
86
|
+
step1 = wf.job(:step1, :input1 => 4)
|
87
|
+
assert_equal 4, step1.run
|
88
|
+
job = wf.job(:double, "TaskInputs#step1" => step1)
|
89
|
+
assert_equal 14, job.run
|
90
|
+
assert_not_equal Task::DEFAULT_NAME, job.name
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_input_dep_override
|
94
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
95
|
+
input :v1, :integer
|
96
|
+
input :v2, :integer
|
97
|
+
task :sum => :integer do |v1,v2|
|
98
|
+
v1 + v2
|
99
|
+
end
|
100
|
+
|
101
|
+
input :input1, :integer
|
102
|
+
task :step1 => :integer do |i| i end
|
103
|
+
|
104
|
+
input :input2, :integer
|
105
|
+
task :step2 => :integer do |i| i end
|
106
|
+
|
107
|
+
dep :step1
|
108
|
+
dep :step2
|
109
|
+
task :my_sum => :integer do
|
110
|
+
dependencies.inject(0){|acc,d| acc += d.load }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
step2 = wf.job(:step2, :input2 => 4)
|
115
|
+
job = wf.job(:my_sum, :input1 => 2, :input2 => 3, "TaskInputs#step2"=> step2)
|
116
|
+
assert_equal 6, job.exec
|
117
|
+
|
118
|
+
job = wf.job(:my_sum, :input1 => 2, :input2 => 3)
|
119
|
+
assert_equal 5, job.run
|
120
|
+
|
121
|
+
TmpFile.with_file(4) do |file|
|
122
|
+
job = wf.job(:my_sum, :input1 => 2, :input2 => 3, "TaskInputs#step2"=> file)
|
123
|
+
assert_equal 6, job.run
|
124
|
+
assert_not_equal Task::DEFAULT_NAME, job.name
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_input_rename
|
129
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
130
|
+
input :v1, :integer
|
131
|
+
input :v2, :integer
|
132
|
+
task :sum => :integer do |v1,v2|
|
133
|
+
v1 + v2
|
134
|
+
end
|
135
|
+
|
136
|
+
input :vv1, :integer
|
137
|
+
input :vv2, :integer
|
138
|
+
dep :sum, :v1 => :vv1, :v2 => :vv2
|
139
|
+
task :my_sum => :integer do
|
140
|
+
dependencies.last.load
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
job = wf.job(:my_sum, :vv1 => 2, :vv2 => 3)
|
145
|
+
assert_equal 5, job.run
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_defaults_in_dep_block
|
149
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
150
|
+
input :v1, :integer
|
151
|
+
input :v2, :integer
|
152
|
+
task :sum => :integer do |v1,v2|
|
153
|
+
v1 + v2
|
154
|
+
end
|
155
|
+
|
156
|
+
input :vv1, :integer
|
157
|
+
input :vv2, :integer, nil, 3
|
158
|
+
dep :sum, :v1 => :placeholder, :v2 => :placeholder do |jobname,options,dependencies|
|
159
|
+
raise "Non-numeric value where integer expected" unless Numeric === options[:vv1]
|
160
|
+
{inputs: {v1: options[:vv1], v2: options[:vv2]} }
|
161
|
+
end
|
162
|
+
task :my_sum => :integer do
|
163
|
+
dependencies.last.load
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
job = wf.job(:my_sum, :vv1 => "2")
|
168
|
+
assert_equal 5, job.run
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_dependency_jobname
|
172
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
173
|
+
input :v1, :integer
|
174
|
+
input :v2, :integer
|
175
|
+
task :sum => :integer do |v1,v2|
|
176
|
+
v1 + v2
|
177
|
+
end
|
178
|
+
|
179
|
+
input :vv1, :integer
|
180
|
+
input :vv2, :integer
|
181
|
+
dep :sum, :v1 => :vv1, :v2 => :vv2, :jobname => "OTHER_NAME"
|
182
|
+
task :my_sum => :integer do
|
183
|
+
dependencies.last.load
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
job = wf.job(:my_sum, "TEST_NAME", :vv1 => 2, :vv2 => 3)
|
188
|
+
assert_equal 5, job.run
|
189
|
+
assert_equal "TEST_NAME", job.clean_name
|
190
|
+
assert_equal "OTHER_NAME", job.step(:sum).clean_name
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_no_param_last_job
|
194
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
195
|
+
input :v1, :integer
|
196
|
+
input :v2, :integer
|
197
|
+
task :sum => :integer do |v1,v2|
|
198
|
+
v1 + v2
|
199
|
+
end
|
200
|
+
|
201
|
+
dep :sum
|
202
|
+
task :my_sum => :integer do
|
203
|
+
dependencies.last.load
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
job = wf.job(:my_sum, :v1 => 2, :v2 => "3")
|
208
|
+
assert_equal 5, job.run
|
209
|
+
refute_equal Task::DEFAULT_NAME, job.name
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_no_param_last_job_block
|
213
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
214
|
+
input :v1, :integer
|
215
|
+
input :v2, :integer
|
216
|
+
task :sum => :integer do |v1,v2|
|
217
|
+
v1 + v2
|
218
|
+
end
|
219
|
+
|
220
|
+
dep :sum do |jobname,options|
|
221
|
+
{inputs: options}
|
222
|
+
end
|
223
|
+
task :my_sum => :integer do
|
224
|
+
dependencies.last.load
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
job = wf.job(:my_sum, :v1 => 2, :v2 => "3")
|
229
|
+
assert_equal 5, job.run
|
230
|
+
refute_equal Task::DEFAULT_NAME, job.name
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
def test_override_inputs_block
|
235
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
236
|
+
input :input1, :string
|
237
|
+
task :step1 => :string do |i| i end
|
238
|
+
|
239
|
+
dep :step1, :input1 => 1 do |id,options|
|
240
|
+
{:inputs => options}
|
241
|
+
end
|
242
|
+
task :step2 => :string do |i| step(:step1).load end
|
243
|
+
end
|
244
|
+
|
245
|
+
job = wf.job(:step2, :input1 => 2)
|
246
|
+
assert_equal 1, job.run
|
247
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
248
|
+
assert_not_equal Task::DEFAULT_NAME, job.step(:step1).name
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_default_inputs_in_block
|
252
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
253
|
+
input :input1, :string
|
254
|
+
task :step1 => :string do |i| i end
|
255
|
+
|
256
|
+
dep :step1 do |id,options|
|
257
|
+
{}
|
258
|
+
end
|
259
|
+
task :step2 => :string do |i| step(:step1).load end
|
260
|
+
end
|
261
|
+
|
262
|
+
job = wf.job(:step2, "SOME_NAME", :input1 => 2)
|
263
|
+
assert_equal "SOME_NAME", job.step(:step1).clean_name
|
264
|
+
assert_equal 2, job.run
|
265
|
+
end
|
266
|
+
|
267
|
+
def test_override_inputs_block_array
|
268
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
269
|
+
input :input1, :string
|
270
|
+
task :step1 => :string do |i| i end
|
271
|
+
|
272
|
+
dep :step1, :input1 => 1 do |id,options|
|
273
|
+
[{:inputs => options}]
|
274
|
+
end
|
275
|
+
input :input2, :string
|
276
|
+
task :step2 => :string do |i| step(:step1).load end
|
277
|
+
end
|
278
|
+
|
279
|
+
job = wf.job(:step2, :input1 => 2)
|
280
|
+
assert_equal 1, job.run
|
281
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
282
|
+
assert_not_equal Task::DEFAULT_NAME, job.step(:step1).name
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_override_inputs
|
286
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
287
|
+
input :input1, :string
|
288
|
+
task :step1 => :string do |i| i end
|
289
|
+
|
290
|
+
dep :step1, :input1 => 1
|
291
|
+
input :input2, :string
|
292
|
+
task :step2 => :string do |i| step(:step1).load end
|
293
|
+
end
|
294
|
+
|
295
|
+
job = wf.job(:step2, :input1 => 2)
|
296
|
+
assert_equal 1, job.run
|
297
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
298
|
+
assert_not_equal Task::DEFAULT_NAME, job.step(:step1).name
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_non_default_inputs
|
302
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
303
|
+
input :input1, :integer, "", 1
|
304
|
+
input :input2, :integer, "", 0
|
305
|
+
task :step1 => :string do |i1,i2| i1 + i2 end
|
306
|
+
|
307
|
+
dep :step1, :input2 => 1
|
308
|
+
task :step2 => :string do |i| step(:step1).load end
|
309
|
+
|
310
|
+
dep :step2
|
311
|
+
task :step3 => :string do |i| step(:step1).load end
|
312
|
+
end
|
313
|
+
|
314
|
+
job = wf.job(:step3, :input1 => 1)
|
315
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
316
|
+
assert_not_equal Task::DEFAULT_NAME, job.step(:step1).name
|
317
|
+
assert_equal 2, job.run
|
318
|
+
|
319
|
+
job = wf.job(:step3, :input1 => 2)
|
320
|
+
assert_equal 3, job.run
|
321
|
+
|
322
|
+
|
323
|
+
job = wf.job(:step3)
|
324
|
+
assert_equal Task::DEFAULT_NAME, job.name
|
325
|
+
assert_not_equal Task::DEFAULT_NAME, job.step(:step1).name
|
326
|
+
end
|
327
|
+
|
328
|
+
def test_can_fail
|
329
|
+
wf = Workflow.annonymous_workflow "TaskInputs" do
|
330
|
+
input :input1, :integer, "", 1
|
331
|
+
task :step1 => :string do |i1|
|
332
|
+
if i1 < 0
|
333
|
+
raise ScoutException
|
334
|
+
else
|
335
|
+
i1
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
dep :step1, :canfail => true
|
340
|
+
task :step2 => :string do |i|
|
341
|
+
if step(:step1).error?
|
342
|
+
0
|
343
|
+
else
|
344
|
+
step(:step1).load
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
assert_equal 1, wf.job(:step2, :input1 => 1).run
|
350
|
+
assert_equal 2, wf.job(:step2, :input1 => 2).run
|
351
|
+
assert_equal 0, wf.job(:step2, :input1 => -2).run
|
352
|
+
end
|
353
|
+
|
354
|
+
end
|
355
|
+
|
@@ -21,6 +21,11 @@ class TestTaskInput < Test::Unit::TestCase
|
|
21
21
|
task :task => :array do
|
22
22
|
inputs
|
23
23
|
end
|
24
|
+
|
25
|
+
dep :task
|
26
|
+
task :task2 => :array do
|
27
|
+
inputs
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
@@ -106,6 +111,7 @@ class TestTaskInput < Test::Unit::TestCase
|
|
106
111
|
def test_save_and_load
|
107
112
|
task = self.example_task
|
108
113
|
|
114
|
+
sss 0
|
109
115
|
TmpFile.with_file("2\n3") do |integer_array_file|
|
110
116
|
inputs = {:string => "String", :integer => 2, :integer_array => integer_array_file, :float_array => %w(1.1 2.2)}
|
111
117
|
original_digest = task.process_inputs(inputs).last
|
@@ -179,4 +185,51 @@ class TestTaskInput < Test::Unit::TestCase
|
|
179
185
|
end
|
180
186
|
end
|
181
187
|
end
|
188
|
+
|
189
|
+
def test_save_and_load_file_array_task2
|
190
|
+
task = self.example_workflow.tasks[:task2]
|
191
|
+
|
192
|
+
TmpFile.with_file do |dir|
|
193
|
+
file1 = File.join(dir, 'subdir1/file')
|
194
|
+
file2 = File.join(dir, 'subdir2/file')
|
195
|
+
|
196
|
+
Open.write(file1, "TEST1")
|
197
|
+
Open.write(file2, "TEST2")
|
198
|
+
inputs = {:string => "String", :integer => 2, :file_array => [file1, file2], :float_array => %w(1.1 2.2)}
|
199
|
+
original_digest = task.process_inputs(inputs).last
|
200
|
+
|
201
|
+
TmpFile.with_file do |save_directory|
|
202
|
+
task.save_inputs(save_directory, inputs)
|
203
|
+
Open.rm(file1)
|
204
|
+
Open.rm(file2)
|
205
|
+
new_inputs = task.load_inputs(save_directory)
|
206
|
+
new_digest = task.process_inputs(new_inputs).last
|
207
|
+
assert_equal original_digest, new_digest
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_save_and_load_array_from_file
|
213
|
+
task = self.example_workflow.tasks[:task]
|
214
|
+
|
215
|
+
TmpFile.with_file do |dir|
|
216
|
+
array = %w(1 2 3 4 5)
|
217
|
+
file1 = File.join(dir, 'subdir1/file')
|
218
|
+
Open.write(file1, array * "\n")
|
219
|
+
inputs = {:array => file1 }
|
220
|
+
original_digest = task.process_inputs(inputs).last
|
221
|
+
|
222
|
+
TmpFile.with_file do |save_directory|
|
223
|
+
iii inputs
|
224
|
+
task.save_inputs(save_directory, inputs)
|
225
|
+
Open.rm(file1)
|
226
|
+
new_inputs = task.load_inputs(save_directory)
|
227
|
+
iii new_inputs
|
228
|
+
new_digest = task.process_inputs(new_inputs).last
|
229
|
+
iii new_digest
|
230
|
+
iii original_digest
|
231
|
+
assert_equal original_digest, new_digest
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
182
235
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
class TestClass < Test::Unit::TestCase
|
5
|
+
def test_function_task
|
6
|
+
wf = Workflow.annonymous_workflow do
|
7
|
+
self.name = "StringLength"
|
8
|
+
def self.str_length(s)
|
9
|
+
s.length
|
10
|
+
end
|
11
|
+
|
12
|
+
input :string, :string
|
13
|
+
task :str_length => :integer
|
14
|
+
end
|
15
|
+
assert_equal 5, wf.job(:str_length, :string => "12345").run
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -26,5 +26,29 @@ class TestWorkflowDocumentation < Test::Unit::TestCase
|
|
26
26
|
assert_match 'test', UsageWorkflow.documentation[:title]
|
27
27
|
assert_match 'presented', UsageWorkflow.documentation[:description]
|
28
28
|
end
|
29
|
+
|
30
|
+
def test_documentation_markdown
|
31
|
+
doc =<<-EOF
|
32
|
+
summary
|
33
|
+
|
34
|
+
description
|
35
|
+
|
36
|
+
# Tasks
|
37
|
+
|
38
|
+
## task1
|
39
|
+
|
40
|
+
task 1 summary
|
41
|
+
|
42
|
+
task 1 description
|
43
|
+
|
44
|
+
## task2
|
45
|
+
task 2 summary
|
46
|
+
|
47
|
+
task 2 description
|
48
|
+
EOF
|
49
|
+
|
50
|
+
assert_includes Workflow.parse_workflow_doc(doc)[:tasks], 'task1'
|
51
|
+
assert_includes Workflow.parse_workflow_doc(doc)[:tasks]['task2'], 'task 2 description'
|
52
|
+
end
|
29
53
|
end
|
30
54
|
|
@@ -47,6 +47,17 @@ class TestWorkflowStep < Test::Unit::TestCase
|
|
47
47
|
end
|
48
48
|
step1.type = :array
|
49
49
|
|
50
|
+
step1.clean
|
51
|
+
res = step1.run(false)
|
52
|
+
refute IO === res
|
53
|
+
step1.join
|
54
|
+
|
55
|
+
step1.clean
|
56
|
+
res = step1.run(true)
|
57
|
+
assert IO === res
|
58
|
+
step1.join
|
59
|
+
step1.clean
|
60
|
+
|
50
61
|
step2 = Step.new tmpfile.step2 do
|
51
62
|
step1 = dependencies.first
|
52
63
|
stream = step1.stream
|
@@ -229,4 +240,102 @@ class TestWorkflowStep < Test::Unit::TestCase
|
|
229
240
|
|
230
241
|
assert_equal times, lines.length
|
231
242
|
end
|
243
|
+
|
244
|
+
def test_fork_stream_fork
|
245
|
+
tmpfile = tmpdir.test_step
|
246
|
+
|
247
|
+
times = 10_000
|
248
|
+
sleep = 0.1 / times
|
249
|
+
|
250
|
+
step1 = Step.new tmpfile.step1, [times, sleep] do |times,sleep|
|
251
|
+
sleep 1
|
252
|
+
Open.open_pipe do |sin|
|
253
|
+
times.times do |i|
|
254
|
+
sin.puts "line-#{i}"
|
255
|
+
sleep sleep
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
step1.type = :array
|
260
|
+
|
261
|
+
|
262
|
+
step2 = Step.new tmpfile.step2 do
|
263
|
+
step1 = dependencies.first
|
264
|
+
stream = step1.stream
|
265
|
+
|
266
|
+
Open.open_pipe do |sin|
|
267
|
+
while line = stream.gets
|
268
|
+
num = line.split("-").last
|
269
|
+
next if num.to_i % 2 == 1
|
270
|
+
sin.puts "S2: " + line
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
step2.type = :array
|
275
|
+
step2.dependencies = [step1]
|
276
|
+
|
277
|
+
step3 = Step.new tmpfile.step3 do
|
278
|
+
step1 = dependencies.first
|
279
|
+
stream = step1.stream
|
280
|
+
|
281
|
+
Open.open_pipe do |sin|
|
282
|
+
while line = stream.gets
|
283
|
+
num = line.split("-").last
|
284
|
+
next if num.to_i % 2 == 0
|
285
|
+
sin.puts "S3: " + line
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
step3.type = :array
|
290
|
+
step3.dependencies = [step1]
|
291
|
+
|
292
|
+
|
293
|
+
step4 = Step.new tmpfile.step4 do
|
294
|
+
step2, step3 = dependencies
|
295
|
+
|
296
|
+
mutex = Mutex.new
|
297
|
+
Open.open_pipe do |sin|
|
298
|
+
t2 = Thread.new do
|
299
|
+
stream2 = step2.stream
|
300
|
+
while line = stream2.gets
|
301
|
+
sin.puts line
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
t3 = Thread.new do
|
306
|
+
stream3 = step3.stream
|
307
|
+
while line = stream3.gets
|
308
|
+
sin.puts line
|
309
|
+
end
|
310
|
+
end
|
311
|
+
t2.join
|
312
|
+
t3.join
|
313
|
+
end
|
314
|
+
end
|
315
|
+
step4.type = :array
|
316
|
+
step4.dependencies = [step2, step3]
|
317
|
+
|
318
|
+
step4.recursive_clean
|
319
|
+
step4.fork
|
320
|
+
assert Array === step4.load
|
321
|
+
assert_equal times, step4.load.size
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_dependency_canfail
|
325
|
+
tmpfile = tmpdir.test_step
|
326
|
+
step1 = Step.new tmpfile.step1, ["12"] do |s|
|
327
|
+
s.length
|
328
|
+
end
|
329
|
+
|
330
|
+
step2 = Step.new tmpfile.step2 do
|
331
|
+
step1 = dependencies.first
|
332
|
+
step1.inputs.first + " has " + step1.load.to_s + " characters"
|
333
|
+
end
|
334
|
+
|
335
|
+
step2.dependencies = [step1]
|
336
|
+
|
337
|
+
assert_equal "12 has 2 characters", step2.run
|
338
|
+
assert_equal "12 has 2 characters", step2.run
|
339
|
+
end
|
340
|
+
|
232
341
|
end
|