scout-gear 8.0.0 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +48 -9
  3. data/Rakefile +6 -1
  4. data/VERSION +1 -1
  5. data/bin/scout +16 -4
  6. data/doc/lib/scout/path.md +35 -0
  7. data/doc/lib/scout/workflow/task.md +13 -0
  8. data/lib/rbbt-scout.rb +2 -1
  9. data/lib/scout/cmd.rb +32 -29
  10. data/lib/scout/concurrent_stream.rb +36 -19
  11. data/lib/scout/exceptions.rb +10 -0
  12. data/lib/scout/indiferent_hash.rb +17 -0
  13. data/lib/scout/log/color.rb +11 -11
  14. data/lib/scout/log/progress/report.rb +8 -5
  15. data/lib/scout/log/progress/util.rb +3 -0
  16. data/lib/scout/log/trap.rb +3 -3
  17. data/lib/scout/log.rb +67 -36
  18. data/lib/scout/meta_extension.rb +34 -0
  19. data/lib/scout/misc/digest.rb +11 -2
  20. data/lib/scout/misc/filesystem.rb +2 -3
  21. data/lib/scout/misc/format.rb +12 -7
  22. data/lib/scout/misc/monitor.rb +11 -0
  23. data/lib/scout/misc/system.rb +48 -0
  24. data/lib/scout/named_array.rb +8 -0
  25. data/lib/scout/offsite/ssh.rb +174 -0
  26. data/lib/scout/offsite/step.rb +100 -0
  27. data/lib/scout/offsite/sync.rb +55 -0
  28. data/lib/scout/offsite.rb +3 -0
  29. data/lib/scout/open/lock.rb +5 -24
  30. data/lib/scout/open/remote.rb +12 -1
  31. data/lib/scout/open/stream.rb +109 -122
  32. data/lib/scout/open/util.rb +9 -0
  33. data/lib/scout/open.rb +12 -11
  34. data/lib/scout/path/find.rb +15 -10
  35. data/lib/scout/path/util.rb +5 -0
  36. data/lib/scout/path.rb +1 -1
  37. data/lib/scout/persist/serialize.rb +4 -4
  38. data/lib/scout/persist.rb +1 -1
  39. data/lib/scout/resource/open.rb +8 -0
  40. data/lib/scout/resource/path.rb +16 -9
  41. data/lib/scout/resource/software.rb +4 -2
  42. data/lib/scout/resource/util.rb +10 -4
  43. data/lib/scout/resource.rb +2 -0
  44. data/lib/scout/tsv/dumper.rb +5 -1
  45. data/lib/scout/tsv/index.rb +28 -86
  46. data/lib/scout/tsv/open.rb +35 -14
  47. data/lib/scout/tsv/parser.rb +22 -5
  48. data/lib/scout/tsv/persist/tokyocabinet.rb +2 -0
  49. data/lib/scout/tsv/stream.rb +204 -0
  50. data/lib/scout/tsv/transformer.rb +11 -0
  51. data/lib/scout/tsv.rb +9 -2
  52. data/lib/scout/work_queue/worker.rb +2 -2
  53. data/lib/scout/work_queue.rb +37 -12
  54. data/lib/scout/workflow/definition.rb +2 -1
  55. data/lib/scout/workflow/deployment/orchestrator.rb +254 -0
  56. data/lib/scout/workflow/deployment.rb +1 -0
  57. data/lib/scout/workflow/step/dependencies.rb +46 -14
  58. data/lib/scout/workflow/step/file.rb +5 -0
  59. data/lib/scout/workflow/step/info.rb +13 -3
  60. data/lib/scout/workflow/step/inputs.rb +5 -0
  61. data/lib/scout/workflow/step/load.rb +1 -1
  62. data/lib/scout/workflow/step/provenance.rb +1 -0
  63. data/lib/scout/workflow/step/status.rb +27 -9
  64. data/lib/scout/workflow/step.rb +82 -30
  65. data/lib/scout/workflow/task/dependencies.rb +116 -0
  66. data/lib/scout/workflow/task/inputs.rb +36 -17
  67. data/lib/scout/workflow/task.rb +12 -109
  68. data/lib/scout/workflow/usage.rb +57 -41
  69. data/lib/scout/workflow.rb +19 -13
  70. data/lib/scout-gear.rb +2 -0
  71. data/lib/scout.rb +6 -0
  72. data/scout-gear.gemspec +38 -7
  73. data/scout_commands/doc +37 -0
  74. data/scout_commands/find +1 -0
  75. data/scout_commands/offsite +30 -0
  76. data/scout_commands/resource/produce +66 -0
  77. data/scout_commands/template +52 -0
  78. data/scout_commands/update +29 -0
  79. data/scout_commands/workflow/info +15 -3
  80. data/scout_commands/workflow/install +105 -0
  81. data/scout_commands/workflow/task +46 -6
  82. data/share/software/install_helpers +2 -2
  83. data/share/templates/command +25 -0
  84. data/share/templates/workflow.rb +14 -0
  85. data/test/scout/offsite/test_ssh.rb +15 -0
  86. data/test/scout/offsite/test_step.rb +32 -0
  87. data/test/scout/offsite/test_sync.rb +36 -0
  88. data/test/scout/offsite/test_task.rb +0 -0
  89. data/test/scout/resource/test_path.rb +6 -0
  90. data/test/scout/test_named_array.rb +6 -0
  91. data/test/scout/test_persist.rb +3 -2
  92. data/test/scout/test_tsv.rb +17 -0
  93. data/test/scout/test_work_queue.rb +64 -42
  94. data/test/scout/tsv/persist/test_adapter.rb +1 -1
  95. data/test/scout/tsv/test_index.rb +14 -0
  96. data/test/scout/tsv/test_parser.rb +35 -0
  97. data/test/scout/tsv/test_stream.rb +200 -0
  98. data/test/scout/tsv/test_transformer.rb +12 -0
  99. data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
  100. data/test/scout/workflow/step/test_dependencies.rb +68 -0
  101. data/test/scout/workflow/step/test_info.rb +17 -0
  102. data/test/scout/workflow/step/test_status.rb +0 -1
  103. data/test/scout/workflow/task/test_dependencies.rb +357 -0
  104. data/test/scout/workflow/task/test_inputs.rb +52 -0
  105. data/test/scout/workflow/test_definition.rb +18 -0
  106. data/test/scout/workflow/test_documentation.rb +24 -0
  107. data/test/scout/workflow/test_step.rb +109 -0
  108. data/test/scout/workflow/test_task.rb +0 -287
  109. data/test/test_scout.rb +9 -0
  110. metadata +89 -5
  111. data/scout_commands/workflow/task_old +0 -706
@@ -0,0 +1,200 @@
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/tsv'
5
+ class TestTSVStream < Test::Unit::TestCase
6
+ def test_paste_stream
7
+ text1=<<-EOF
8
+ #: :sep=" "
9
+ #Row LabelA LabelB LabelC
10
+ row1 A B C
11
+ row2 AA BB CC
12
+ row3 AAA BBB CCC
13
+ EOF
14
+
15
+ text2=<<-EOF
16
+ #: :sep=" "
17
+ #Row Labela Labelb
18
+ row1 a b
19
+ row2 aa bb
20
+ row3 aaa bbb
21
+ EOF
22
+
23
+ text3=<<-EOF
24
+ #: :sep=" "
25
+ #Row LabelC
26
+ row1 c
27
+ row2 cc
28
+ row3 ccc
29
+ EOF
30
+
31
+ s1 = StringIO.new text1
32
+ s2 = StringIO.new text2
33
+ s3 = StringIO.new text3
34
+ tsv = TSV.open TSV.paste_streams([s1,s2,s3], :sep => " ", :type => :list)
35
+ assert_equal ["A", "B", "C", "a", "b", "c"], tsv["row1"]
36
+ assert_equal ["AA", "BB", "CC", "aa", "bb", "cc"], tsv["row2"]
37
+ assert_equal ["AAA", "BBB", "CCC", "aaa", "bbb", "ccc"], tsv["row3"]
38
+ end
39
+
40
+ def test_paste_stream_sort
41
+ text1=<<-EOF
42
+ #: :sep=" "
43
+ #Row LabelA LabelB LabelC
44
+ row2 AA BB CC
45
+ row1 A B C
46
+ row3 AAA BBB CCC
47
+ EOF
48
+
49
+ text2=<<-EOF
50
+ #: :sep=" "
51
+ #Row Labela Labelb
52
+ row1 a b
53
+ row3 aaa bbb
54
+ row2 aa bb
55
+ EOF
56
+
57
+ text3=<<-EOF
58
+ #: :sep=" "
59
+ #Row Labelc
60
+ row3 ccc
61
+ row1 c
62
+ row2 cc
63
+ EOF
64
+
65
+ s1 = StringIO.new text1
66
+ s2 = StringIO.new text2
67
+ s3 = StringIO.new text3
68
+ tsv = TSV.open TSV.paste_streams([s1,s2,s3], :sep => " ", :type => :list, :sort => true)
69
+ assert_equal "Row", tsv.key_field
70
+ assert_equal %w(LabelA LabelB LabelC Labela Labelb Labelc), tsv.fields
71
+ assert_equal ["A", "B", "C", "a", "b", "c"], tsv["row1"]
72
+ assert_equal ["AA", "BB", "CC", "aa", "bb", "cc"], tsv["row2"]
73
+ assert_equal ["AAA", "BBB", "CCC", "aaa", "bbb", "ccc"], tsv["row3"]
74
+ end
75
+
76
+ def test_paste_stream_missing_2
77
+ text1=<<-EOF
78
+ #: :sep=" "
79
+ #Row LabelA LabelB LabelC
80
+ row2 AA BB CC
81
+ row1 A B C
82
+ EOF
83
+
84
+ text2=<<-EOF
85
+ #: :sep=" "
86
+ #Row Labela Labelb
87
+ row2 aa bb
88
+ EOF
89
+
90
+ text3=<<-EOF
91
+ #: :sep=" "
92
+ #Row Labelc
93
+ row3 ccc
94
+ row2 cc
95
+ EOF
96
+
97
+ s1 = StringIO.new text1
98
+ s2 = StringIO.new text2
99
+ s3 = StringIO.new text3
100
+ tsv = TSV.open TSV.paste_streams([s1,s2,s3], :sep => " ", :type => :list, :sort => true)
101
+ assert_equal "Row", tsv.key_field
102
+ assert_equal %w(LabelA LabelB LabelC Labela Labelb Labelc), tsv.fields
103
+ assert_equal ["A", "B", "C", "", "", ""], tsv["row1"]
104
+ assert_equal ["AA", "BB", "CC", "aa", "bb", "cc"], tsv["row2"]
105
+ assert_equal ["", "", "", "", "", "ccc"], tsv["row3"]
106
+ end
107
+
108
+ def test_paste_stream_missing
109
+ text1=<<-EOF
110
+ #: :sep=" "
111
+ #Row LabelA LabelB LabelC
112
+ row2 AA BB CC
113
+ row1 A B C
114
+ EOF
115
+
116
+ text2=<<-EOF
117
+ #: :sep=" "
118
+ #Row Labela Labelb
119
+ row2 aa bb
120
+ EOF
121
+
122
+ text3=<<-EOF
123
+ #: :sep=" "
124
+ #Row Labelc
125
+ row3 ccc
126
+ row2 cc
127
+ EOF
128
+
129
+ s1 = StringIO.new text1
130
+ s2 = StringIO.new text2
131
+ s3 = StringIO.new text3
132
+ tsv = TSV.open TSV.paste_streams([s1,s2,s3], :sep => " ", :type => :list, :sort => true)
133
+ assert_equal "Row", tsv.key_field
134
+ assert_equal %w(LabelA LabelB LabelC Labela Labelb Labelc), tsv.fields
135
+ assert_equal ["A", "B", "C", "", "", ""], tsv["row1"]
136
+ assert_equal ["AA", "BB", "CC", "aa", "bb", "cc"], tsv["row2"]
137
+ assert_equal ["", "", "", "", "", "ccc"], tsv["row3"]
138
+ end
139
+
140
+ def test_paste_stream_missing_3
141
+ text1=<<-EOF
142
+ #: :sep=" "
143
+ #Row LabelA LabelB LabelC
144
+ row2 AA BB CC
145
+ row1 A B C
146
+ EOF
147
+
148
+ text2=<<-EOF
149
+ #: :sep=" "
150
+ #Row Labelc
151
+ EOF
152
+
153
+ s1 = StringIO.new text1
154
+ s2 = StringIO.new text2
155
+ tsv = TSV.open TSV.paste_streams([s1,s2], :sep => " ", :type => :list, :sort => true)
156
+ assert_equal "Row", tsv.key_field
157
+ assert_equal %w(LabelA LabelB LabelC Labelc), tsv.fields
158
+ assert_equal ["A", "B", "C", ""], tsv["row1"]
159
+ assert_equal ["AA", "BB", "CC", ""], tsv["row2"]
160
+ end
161
+
162
+ def test_paste_stream_same_field
163
+ text1=<<-EOF
164
+ #: :sep=" "
165
+ #Row LabelA
166
+ row1 A
167
+ row2 AA
168
+ EOF
169
+
170
+ text2=<<-EOF
171
+ #: :sep=" "
172
+ #Row LabelA
173
+ row2 AAA
174
+ EOF
175
+
176
+ s1 = StringIO.new text1
177
+ s2 = StringIO.new text2
178
+ tsv = TSV.open TSV.paste_streams([s1,s2], :sep => " ", :type => :double, :sort => false, :same_fields => true)
179
+ assert_equal "Row", tsv.key_field
180
+ assert_equal ["AA", "AAA"], tsv["row2"][0]
181
+ end
182
+
183
+ def test_paste_stream_nohead
184
+ text1=<<-EOF
185
+ row1\tA
186
+ row2\tAA
187
+ EOF
188
+
189
+ text2=<<-EOF
190
+ row2\tAAA
191
+ EOF
192
+
193
+ s1 = StringIO.new text1
194
+ s2 = StringIO.new text2
195
+ tsv = TSV.open TSV.paste_streams([s1,s2], :type => :double, :sort => false, :same_fields => true)
196
+ assert_equal ["AA", "AAA"], tsv["row2"][0]
197
+ end
198
+
199
+ end
200
+
@@ -105,4 +105,16 @@ row2 A2|A22 B2|B22
105
105
  assert_equal "A1", tsv.to_single["row1"]
106
106
  assert_equal "A2", tsv.to_single["row2"]
107
107
  end
108
+
109
+ def test_to_flat
110
+ content =<<-EOF
111
+ #: :sep=" "
112
+ #ID ValueA ValueB
113
+ row1 A1|A11 B1|B11
114
+ row2 A2|A22 B2|B22
115
+ EOF
116
+
117
+ tsv = TSV.open(content)
118
+ assert_equal %w(A1 A11 B1 B11), tsv.to_flat["row1"]
119
+ end
108
120
  end
@@ -0,0 +1,272 @@
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 TestOrchestrator < Test::Unit::TestCase
5
+ setup do
6
+ module TestWF
7
+ extend Workflow
8
+
9
+ MULT = 0.01
10
+ task :a => :text do
11
+ sleep(TestWF::MULT * (rand(10) + 2))
12
+ end
13
+
14
+ dep :a
15
+ task :b => :text do
16
+ sleep(TestWF::MULT * (rand(10) + 2))
17
+ end
18
+
19
+ dep :a
20
+ dep :b
21
+ task :c => :text do
22
+ sleep(TestWF::MULT * (rand(10) + 2))
23
+ end
24
+
25
+ dep :c
26
+ task :d => :text do
27
+ sleep(TestWF::MULT * (rand(10) + 2))
28
+ end
29
+
30
+ dep :c
31
+ task :e => :text do
32
+ sleep(TestWF::MULT * (rand(10) + 2))
33
+ end
34
+ end
35
+ end
36
+
37
+ def TODO_test_orchestrate_resources
38
+
39
+ jobs =[]
40
+
41
+ num = 10
42
+ num.times do |i|
43
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
44
+ end
45
+ jobs.each do |j| j.recursive_clean end
46
+
47
+ rules = YAML.load <<-EOF
48
+ defaults:
49
+ log: 4
50
+ default_resources:
51
+ IO: 1
52
+ TestWF:
53
+ a:
54
+ resources:
55
+ cpus: 7
56
+ b:
57
+ resources:
58
+ cpus: 2
59
+ c:
60
+ resources:
61
+ cpus: 10
62
+ d:
63
+ resources:
64
+ cpus: 15
65
+ EOF
66
+
67
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
68
+ Log.with_severity 0 do
69
+ orchestrator.process(rules, jobs)
70
+ end
71
+
72
+ data = Workflow.trace jobs, :plot_data => true
73
+ eend = data.column("End.second").values.collect{|v| v.to_f}.max
74
+ second_cpus = TSV.setup({}, "Second~CPUS#:type=:single#:cast=:to_f")
75
+ (0..eend.to_i).each do |second|
76
+ tasks = data.select("Start.second"){|s| s <= second}.select("End.second"){|s| s > second}
77
+ cpus = 0
78
+ tasks.through :key, ["Workflow", "Task"] do |k, values|
79
+ workflow, task = values
80
+ cpus += rules[workflow][task.to_s]["resources"]["cpus"]
81
+ end
82
+ second_cpus[second] = cpus
83
+ end
84
+
85
+ assert Misc.mean(second_cpus.values) > 15
86
+ assert Misc.mean(second_cpus.values) < 30
87
+ end
88
+
89
+ def TODO_test_orchestrate_erase
90
+
91
+ jobs =[]
92
+
93
+ num = 10
94
+ num.times do |i|
95
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
96
+ end
97
+ jobs.each do |j| j.recursive_clean end
98
+
99
+ rules = YAML.load <<-EOF
100
+ defaults:
101
+ log: 4
102
+ default_resources:
103
+ IO: 1
104
+ TestWF:
105
+ a:
106
+ erase: true
107
+ resources:
108
+ cpus: 7
109
+ b:
110
+ erase: true
111
+ resources:
112
+ cpus: 2
113
+ c:
114
+ resources:
115
+ cpus: 10
116
+ d:
117
+ resources:
118
+ cpus: 15
119
+ EOF
120
+
121
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
122
+ Log.with_severity 3 do
123
+ orchestrator.process(rules, jobs)
124
+ end
125
+
126
+ jobs.each do |job|
127
+ assert job.step(:c).dependencies.empty?
128
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
129
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
130
+ end
131
+
132
+ end
133
+
134
+ def TODO_test_orchestrate_default
135
+
136
+ jobs =[]
137
+
138
+ num = 3
139
+ num.times do |i|
140
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
141
+ end
142
+ jobs.each do |j| j.recursive_clean end
143
+
144
+ rules = YAML.load <<-EOF
145
+ defaults:
146
+ erase: true
147
+ log: 4
148
+ default_resources:
149
+ IO: 1
150
+ TestWF:
151
+ a:
152
+ erase: true
153
+ resources:
154
+ cpus: 7
155
+ b:
156
+ erase: true
157
+ resources:
158
+ cpus: 2
159
+ c:
160
+ erase: false
161
+ resources:
162
+ cpus: 10
163
+ d:
164
+ resources:
165
+ cpus: 15
166
+ EOF
167
+
168
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
169
+ Log.with_severity 3 do
170
+ orchestrator.process(rules, jobs)
171
+ end
172
+
173
+ jobs.each do |job|
174
+ assert job.step(:c).dependencies.empty?
175
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
176
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
177
+ end
178
+
179
+ end
180
+
181
+ def TODO_test_orchestrate_top_level
182
+
183
+ jobs =[]
184
+
185
+ num = 3
186
+ num.times do |i|
187
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
188
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:c, name + " #{i}") }
189
+ end
190
+ jobs.each do |j| j.recursive_clean end
191
+
192
+ rules = YAML.load <<-EOF
193
+ defaults:
194
+ erase: true
195
+ log: 4
196
+ default_resources:
197
+ IO: 1
198
+ TestWF:
199
+ a:
200
+ resources:
201
+ cpus: 7
202
+ b:
203
+ resources:
204
+ cpus: 2
205
+ c:
206
+ resources:
207
+ cpus: 10
208
+ d:
209
+ resources:
210
+ cpus: 15
211
+ EOF
212
+
213
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
214
+ Log.with_severity 3 do
215
+ orchestrator.process(rules, jobs)
216
+ end
217
+
218
+ jobs.each do |job|
219
+ next unless job.task_name.to_s == 'd'
220
+ assert job.step(:c).dependencies.empty?
221
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/a/")}.any?
222
+ assert job.step(:c).info[:archived_info].keys.select{|k| k.include?("TestWF/b/")}.any?
223
+ end
224
+
225
+ end
226
+
227
+ def TODO_test_orchestrate_top_level_double_dep
228
+
229
+ jobs =[]
230
+
231
+ num = 10
232
+ num.times do |i|
233
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:e, name + " #{i}") }
234
+ jobs.concat %w(TEST1 TEST2).collect{|name| TestWF.job(:d, name + " #{i}") }
235
+ end
236
+ jobs.each do |j| j.recursive_clean end
237
+
238
+ rules = YAML.load <<-EOF
239
+ defaults:
240
+ erase: true
241
+ log: 4
242
+ default_resources:
243
+ IO: 1
244
+ TestWF:
245
+ a:
246
+ resources:
247
+ cpus: 7
248
+ b:
249
+ resources:
250
+ cpus: 2
251
+ c:
252
+ resources:
253
+ cpus: 10
254
+ d:
255
+ resources:
256
+ cpus: 15
257
+ EOF
258
+
259
+ orchestrator = Workflow::Orchestrator.new(TestWF::MULT, "cpus" => 30, "IO" => 4, "size" => 10 )
260
+ Log.with_severity 3 do
261
+ orchestrator.process(rules, jobs)
262
+ end
263
+
264
+ jobs.each do |job|
265
+ next unless job.task_name.to_s == 'd' || job.task_name.to_s == 'e'
266
+ assert job.info[:archived_info].keys.select{|k| k.include?("TestWF/c/")}.any?
267
+ assert job.info[:archived_info].keys.select{|k| k.include?("TestWF/c/")}.any?
268
+ end
269
+
270
+ end
271
+ end
272
+
@@ -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,21 @@ 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
+ end
28
45
  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?