scout-gear 8.0.0 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +26 -9
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +15 -4
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/scout/cmd.rb +23 -24
  9. data/lib/scout/concurrent_stream.rb +36 -19
  10. data/lib/scout/exceptions.rb +10 -0
  11. data/lib/scout/log/color.rb +11 -11
  12. data/lib/scout/log/progress/report.rb +7 -5
  13. data/lib/scout/log/progress/util.rb +3 -0
  14. data/lib/scout/log/trap.rb +3 -3
  15. data/lib/scout/log.rb +64 -36
  16. data/lib/scout/meta_extension.rb +34 -0
  17. data/lib/scout/misc/digest.rb +11 -2
  18. data/lib/scout/misc/format.rb +12 -7
  19. data/lib/scout/misc/monitor.rb +11 -0
  20. data/lib/scout/misc/system.rb +48 -0
  21. data/lib/scout/named_array.rb +8 -0
  22. data/lib/scout/offsite/ssh.rb +171 -0
  23. data/lib/scout/offsite/step.rb +83 -0
  24. data/lib/scout/offsite/sync.rb +55 -0
  25. data/lib/scout/offsite.rb +3 -0
  26. data/lib/scout/open/lock.rb +5 -24
  27. data/lib/scout/open/remote.rb +12 -1
  28. data/lib/scout/open/stream.rb +110 -122
  29. data/lib/scout/open/util.rb +9 -0
  30. data/lib/scout/open.rb +5 -4
  31. data/lib/scout/path/find.rb +15 -10
  32. data/lib/scout/path/util.rb +5 -0
  33. data/lib/scout/persist/serialize.rb +3 -3
  34. data/lib/scout/persist.rb +1 -1
  35. data/lib/scout/resource/path.rb +4 -0
  36. data/lib/scout/resource/util.rb +10 -4
  37. data/lib/scout/tsv/dumper.rb +2 -0
  38. data/lib/scout/tsv/index.rb +28 -86
  39. data/lib/scout/tsv/open.rb +35 -14
  40. data/lib/scout/tsv/parser.rb +9 -2
  41. data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
  42. data/lib/scout/tsv/stream.rb +204 -0
  43. data/lib/scout/tsv/transformer.rb +11 -0
  44. data/lib/scout/tsv.rb +9 -2
  45. data/lib/scout/work_queue/worker.rb +2 -2
  46. data/lib/scout/work_queue.rb +36 -12
  47. data/lib/scout/workflow/definition.rb +2 -1
  48. data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
  49. data/lib/scout/workflow/deployment.rb +1 -0
  50. data/lib/scout/workflow/step/dependencies.rb +37 -11
  51. data/lib/scout/workflow/step/file.rb +5 -0
  52. data/lib/scout/workflow/step/info.rb +5 -3
  53. data/lib/scout/workflow/step/load.rb +1 -1
  54. data/lib/scout/workflow/step/provenance.rb +1 -0
  55. data/lib/scout/workflow/step/status.rb +6 -8
  56. data/lib/scout/workflow/step.rb +75 -30
  57. data/lib/scout/workflow/task/dependencies.rb +114 -0
  58. data/lib/scout/workflow/task/inputs.rb +27 -13
  59. data/lib/scout/workflow/task.rb +9 -108
  60. data/lib/scout/workflow/usage.rb +40 -12
  61. data/lib/scout/workflow.rb +4 -2
  62. data/lib/scout-gear.rb +2 -0
  63. data/lib/scout.rb +6 -0
  64. data/scout-gear.gemspec +32 -7
  65. data/scout_commands/doc +37 -0
  66. data/scout_commands/find +1 -0
  67. data/scout_commands/offsite +30 -0
  68. data/scout_commands/update +29 -0
  69. data/scout_commands/workflow/info +15 -3
  70. data/scout_commands/workflow/install +102 -0
  71. data/scout_commands/workflow/task +26 -5
  72. data/test/scout/offsite/test_ssh.rb +15 -0
  73. data/test/scout/offsite/test_step.rb +33 -0
  74. data/test/scout/offsite/test_sync.rb +36 -0
  75. data/test/scout/offsite/test_task.rb +0 -0
  76. data/test/scout/resource/test_path.rb +6 -0
  77. data/test/scout/test_named_array.rb +6 -0
  78. data/test/scout/test_persist.rb +3 -2
  79. data/test/scout/test_tsv.rb +17 -0
  80. data/test/scout/test_work_queue.rb +63 -41
  81. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  82. data/test/scout/tsv/test_index.rb +14 -0
  83. data/test/scout/tsv/test_parser.rb +14 -0
  84. data/test/scout/tsv/test_stream.rb +200 -0
  85. data/test/scout/tsv/test_transformer.rb +12 -0
  86. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  87. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  88. data/test/scout/workflow/step/test_info.rb +18 -0
  89. data/test/scout/workflow/step/test_status.rb +0 -1
  90. data/test/scout/workflow/task/test_dependencies.rb +355 -0
  91. data/test/scout/workflow/task/test_inputs.rb +53 -0
  92. data/test/scout/workflow/test_definition.rb +18 -0
  93. data/test/scout/workflow/test_documentation.rb +24 -0
  94. data/test/scout/workflow/test_step.rb +109 -0
  95. data/test/scout/workflow/test_task.rb +0 -287
  96. data/test/test_scout.rb +9 -0
  97. metadata +83 -5
  98. 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
@@ -15,7 +15,6 @@ class TestStepStatus < Test::Unit::TestCase
15
15
 
16
16
  step2.dependencies = [step1]
17
17
 
18
- sss 0
19
18
  Misc.with_env "SCOUT_UPDATE", "true" do
20
19
  step2.run
21
20
  assert step2.updated?
@@ -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