scout-gear 10.8.4 → 10.10.1

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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +38 -0
  3. data/README.md +352 -0
  4. data/VERSION +1 -1
  5. data/bin/scout +4 -1
  6. data/doc/Association.md +288 -0
  7. data/doc/Entity.md +296 -0
  8. data/doc/KnowledgeBase.md +433 -0
  9. data/doc/Persist.md +356 -0
  10. data/doc/Semaphore.md +171 -0
  11. data/doc/TSV.md +449 -0
  12. data/doc/WorkQueue.md +359 -0
  13. data/doc/Workflow.md +586 -0
  14. data/lib/scout/association.rb +4 -2
  15. data/lib/scout/entity/identifiers.rb +1 -1
  16. data/lib/scout/entity/object.rb +1 -1
  17. data/lib/scout/entity/property.rb +5 -5
  18. data/lib/scout/entity.rb +1 -1
  19. data/lib/scout/knowledge_base/description.rb +1 -1
  20. data/lib/scout/knowledge_base/list.rb +7 -2
  21. data/lib/scout/knowledge_base/registry.rb +4 -5
  22. data/lib/scout/knowledge_base.rb +20 -2
  23. data/lib/scout/monitor.rb +10 -6
  24. data/lib/scout/persist/engine/packed_index.rb +2 -2
  25. data/lib/scout/persist/engine/sharder.rb +1 -1
  26. data/lib/scout/persist/tsv.rb +1 -0
  27. data/lib/scout/semaphore.rb +1 -1
  28. data/lib/scout/tsv/dumper.rb +3 -3
  29. data/lib/scout/tsv/open.rb +1 -0
  30. data/lib/scout/tsv/parser.rb +1 -1
  31. data/lib/scout/tsv/transformer.rb +1 -0
  32. data/lib/scout/tsv/util.rb +2 -2
  33. data/lib/scout/work_queue/socket.rb +1 -1
  34. data/lib/scout/work_queue/worker.rb +7 -5
  35. data/lib/scout/workflow/definition.rb +11 -0
  36. data/lib/scout/workflow/deployment/local.rb +288 -0
  37. data/lib/scout/workflow/deployment/orchestrator/batches.rb +130 -0
  38. data/lib/scout/workflow/deployment/orchestrator/chains.rb +104 -0
  39. data/lib/scout/workflow/deployment/orchestrator/rules.rb +256 -0
  40. data/lib/scout/workflow/deployment/orchestrator/workload.rb +67 -0
  41. data/lib/scout/workflow/deployment/scheduler/job.rb +740 -0
  42. data/lib/scout/workflow/deployment/scheduler/lfs.rb +125 -0
  43. data/lib/scout/workflow/deployment/scheduler/pbs.rb +176 -0
  44. data/lib/scout/workflow/deployment/scheduler/slurm.rb +158 -0
  45. data/lib/scout/workflow/deployment/scheduler.rb +73 -0
  46. data/lib/scout/workflow/deployment.rb +10 -1
  47. data/lib/scout/workflow/entity.rb +22 -1
  48. data/lib/scout/workflow/exceptions.rb +2 -0
  49. data/lib/scout/workflow/step/config.rb +6 -3
  50. data/lib/scout/workflow/step/file.rb +4 -0
  51. data/lib/scout/workflow/step/info.rb +10 -4
  52. data/lib/scout/workflow/step/progress.rb +52 -0
  53. data/lib/scout/workflow/step.rb +39 -5
  54. data/lib/scout/workflow/task/inputs.rb +1 -1
  55. data/lib/scout/workflow/task.rb +2 -0
  56. data/lib/scout/workflow/usage.rb +3 -2
  57. data/lib/scout/workflow/util.rb +22 -0
  58. data/scout-gear.gemspec +37 -7
  59. data/scout_commands/batch/list +1 -1
  60. data/scout_commands/cat +86 -0
  61. data/scout_commands/doc +3 -1
  62. data/scout_commands/entity +151 -0
  63. data/scout_commands/system/status +238 -0
  64. data/scout_commands/workflow/cmd +5 -13
  65. data/scout_commands/workflow/info +23 -10
  66. data/scout_commands/workflow/install +1 -1
  67. data/scout_commands/workflow/task +61 -25
  68. data/test/scout/entity/test_property.rb +1 -1
  69. data/test/scout/knowledge_base/test_registry.rb +19 -0
  70. data/test/scout/test_work_queue.rb +1 -1
  71. data/test/scout/work_queue/test_worker.rb +12 -10
  72. data/test/scout/workflow/deployment/orchestrator/test_batches.rb +138 -0
  73. data/test/scout/workflow/deployment/orchestrator/test_chains.rb +171 -0
  74. data/test/scout/workflow/deployment/orchestrator/test_rules.rb +219 -0
  75. data/test/scout/workflow/deployment/orchestrator/test_workload.rb +117 -0
  76. data/test/scout/workflow/deployment/scheduler/test_job.rb +31 -0
  77. data/test/scout/workflow/deployment/scheduler/test_lfs.rb +32 -0
  78. data/test/scout/workflow/deployment/scheduler/test_pbs.rb +32 -0
  79. data/test/scout/workflow/deployment/scheduler/test_slurm.rb +32 -0
  80. data/test/scout/workflow/deployment/{test_orchestrator.rb → test_local.rb} +161 -33
  81. data/test/scout/workflow/deployment/test_scheduler.rb +75 -0
  82. data/test/scout/workflow/deployment/test_trace.rb +1 -1
  83. data/test/scout/workflow/step/test_progress.rb +27 -0
  84. data/test/scout/workflow/task/test_inputs.rb +17 -0
  85. data/test/test_helper.rb +2 -1
  86. metadata +36 -6
  87. data/doc/lib/scout/path.md +0 -35
  88. data/doc/lib/scout/workflow/task.md +0 -13
  89. data/lib/scout/workflow/deployment/orchestrator.rb +0 -292
@@ -0,0 +1,138 @@
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
+
5
+ module TestWFA
6
+ extend Workflow
7
+
8
+ task :a1 => :string do self.task_name.to_s end
9
+
10
+ dep :a1
11
+ task :a2 => :string do self.task_name.to_s end
12
+
13
+ dep :a2
14
+ task :a3 => :string do self.task_name.to_s end
15
+ end
16
+
17
+ module TestWFB
18
+ extend Workflow
19
+
20
+ dep TestWFA, :a2
21
+ task :b1 => :string do self.task_name.to_s end
22
+
23
+ dep :b1
24
+ task :b2 => :string do self.task_name.to_s end
25
+ end
26
+
27
+ module TestWFC
28
+ extend Workflow
29
+
30
+ dep TestWFA, :a1
31
+ dep_task :c1, TestWFB, :b2
32
+
33
+ task :c2 => :string do self.task_name.to_s end
34
+
35
+ dep :c1
36
+ dep :c2
37
+ task :c3 => :string do self.task_name.to_s end
38
+
39
+ dep_task :c4, TestWFC, :c3
40
+ end
41
+
42
+ module TestWFD
43
+ extend Workflow
44
+
45
+ dep TestWFC, :c3, :jobname => "First c3"
46
+ dep TestWFC, :c3, :jobname => "Second c3"
47
+ task :d1 => :string do self.task_name.to_s end
48
+ end
49
+
50
+ module TestDeepWF
51
+ extend Workflow
52
+
53
+ dep_task :deep1, TestWFD, :d1
54
+
55
+ input :size, :integer, "Number of dependencies", 100
56
+ dep :deep1 do |jobname,options|
57
+ options[:size].to_i.times.collect{|i|
58
+ {:jobname => "step-#{i}"}
59
+ }
60
+ end
61
+ task :suite => :array do
62
+ end
63
+ end
64
+
65
+ class TestOrchestrateBatches < Test::Unit::TestCase
66
+
67
+ RULES = IndiferentHash.setup(YAML.load(<<-EOF))
68
+ ---
69
+ defaults:
70
+ queue: first_queue
71
+ time: 1h
72
+ log: 2
73
+ config_keys: key1 value1 token1
74
+ chains:
75
+ chain_a_b:
76
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1, TestWFA#a2
77
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
78
+ chain_a:
79
+ workflow: TestWFA
80
+ tasks: a1, a2, a3
81
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
82
+ chain_b:
83
+ workflow: TestWFB
84
+ tasks: b1, b2
85
+ chain_b2:
86
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1
87
+ chain_d:
88
+ tasks: TestWFD#d1, TestWFC#c1, TestWFC#c2, TestWFC#c3
89
+ TestWFA:
90
+ defaults:
91
+ log: 4
92
+ config_keys: key4 value4 token4
93
+ time: 10min
94
+ a1:
95
+ cpus: 10
96
+ config_keys: key5 value5 token5
97
+ TestWFC:
98
+ defaults:
99
+ skip: true
100
+ log: 4
101
+ time: 10s
102
+ EOF
103
+
104
+ def test_chain_batches
105
+ job = TestWFD.job(:d1, nil)
106
+ job.recursive_clean
107
+
108
+ job_chains_map = Workflow::Orchestrator.job_chains(RULES, job)
109
+ workload = Workflow::Orchestrator.job_workload(job)
110
+ batches = Workflow::Orchestrator.chain_batches(RULES, job_chains_map, workload)
111
+ assert_equal 3, batches.length
112
+ end
113
+
114
+
115
+ def test_job_batches_d
116
+ job = TestWFD.job(:d1, nil)
117
+ job.recursive_clean
118
+
119
+ batches = Workflow::Orchestrator.job_batches(RULES, [job])
120
+ assert_equal 3, batches.length
121
+ end
122
+
123
+ def test_job_batches_c4
124
+ job = TestWFC.job(:c4, nil)
125
+ job.recursive_clean
126
+
127
+ batches = Workflow::Orchestrator.job_batches(RULES, job)
128
+ assert_equal 1, batches.length
129
+ end
130
+
131
+ def test_job_batches_a2
132
+ job = TestWFA.job(:a2, nil)
133
+ job.recursive_clean
134
+
135
+ batches = Workflow::Orchestrator.job_batches({}, job)
136
+ assert_equal 2, batches.length
137
+ end
138
+ end
@@ -0,0 +1,171 @@
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
+
6
+ module TestWFA
7
+ extend Workflow
8
+
9
+ task :a1 => :string do self.task_name.to_s end
10
+
11
+ dep :a1
12
+ task :a2 => :string do self.task_name.to_s end
13
+
14
+ dep :a2
15
+ task :a3 => :string do self.task_name.to_s end
16
+ end
17
+
18
+ module TestWFB
19
+ extend Workflow
20
+
21
+ dep TestWFA, :a2
22
+ task :b1 => :string do self.task_name.to_s end
23
+
24
+ dep :b1
25
+ task :b2 => :string do self.task_name.to_s end
26
+ end
27
+
28
+ module TestWFC
29
+ extend Workflow
30
+
31
+ dep TestWFA, :a1
32
+ dep_task :c1, TestWFB, :b2
33
+
34
+ task :c2 => :string do self.task_name.to_s end
35
+
36
+ dep :c1
37
+ dep :c2
38
+ task :c3 => :string do self.task_name.to_s end
39
+
40
+ dep_task :c4, TestWFC, :c3
41
+ end
42
+
43
+ module TestWFD
44
+ extend Workflow
45
+
46
+ dep TestWFC, :c3, :jobname => "First c3"
47
+ dep TestWFC, :c3, :jobname => "Second c3"
48
+ task :d1 => :string do self.task_name.to_s end
49
+ end
50
+
51
+ module TestDeepWF
52
+ extend Workflow
53
+
54
+ dep_task :deep1, TestWFD, :d1
55
+
56
+ input :size, :integer, "Number of dependencies", 100
57
+ dep :deep1 do |jobname,options|
58
+ options[:size].to_i.times.collect{|i|
59
+ {:jobname => "step-#{i}"}
60
+ }
61
+ end
62
+ task :suite => :array do
63
+ end
64
+ end
65
+
66
+ class TestOrchestrateChains < Test::Unit::TestCase
67
+
68
+ RULES = IndiferentHash.setup(YAML.load(<<-EOF))
69
+ ---
70
+ defaults:
71
+ queue: first_queue
72
+ time: 1h
73
+ log: 2
74
+ config_keys: key1 value1 token1
75
+ chains:
76
+ chain_a_b:
77
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1, TestWFA#a2
78
+ comment: Should not include TestWFA#a1
79
+ chain_a:
80
+ workflow: TestWFA
81
+ tasks: a1, a2, a3
82
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
83
+ chain_b:
84
+ workflow: TestWFB
85
+ tasks: b1, b2
86
+ chain_b2:
87
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1
88
+ chain_d:
89
+ tasks: TestWFD#d1, TestWFC#c1, TestWFC#c2, TestWFC#c3
90
+ TestWFA:
91
+ defaults:
92
+ log: 4
93
+ config_keys: key4 value4 token4
94
+ a1:
95
+ cpus: 10
96
+ config_keys: key5 value5 token5
97
+ TestWFC:
98
+ defaults:
99
+ skip: true
100
+ log: 4
101
+ EOF
102
+
103
+ def test_parse_chains
104
+ chains = Workflow::Orchestrator.parse_chains RULES
105
+ assert chains[:chain_a][:tasks]["TestWFA"].include?("a1")
106
+ end
107
+
108
+ def test_job_chain_a
109
+ job = TestWFA.job(:a3, nil)
110
+ job.recursive_clean
111
+
112
+ job_chains = Workflow::Orchestrator.job_chains(RULES, job)
113
+ job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
114
+
115
+ assert_equal %w(chain_a_b chain_a), job_chains.fields
116
+ assert_equal 3, job_chains["chain_a"].last[:jobs].length
117
+ assert_equal job, job_chains["chain_a"].last[:top_level]
118
+ end
119
+
120
+ def test_job_chain_b
121
+ job = TestWFB.job(:b2, nil)
122
+ job.recursive_clean
123
+
124
+ job_chains = Workflow::Orchestrator.job_chains(RULES, job)
125
+ job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
126
+
127
+ assert_equal %w(chain_a chain_b chain_b2 chain_a_b).sort, job_chains.fields.sort
128
+
129
+ assert_equal 2, job_chains["chain_a"].last[:jobs].length
130
+ assert_equal job.step("a2"), job_chains["chain_a"].last[:top_level]
131
+
132
+ assert_equal 2, job_chains["chain_b"].last[:jobs].length
133
+ assert_equal job, job_chains["chain_b"].last[:top_level]
134
+
135
+ assert_equal 2, job_chains["chain_b2"].last[:jobs].length
136
+ assert_equal job, job_chains["chain_b2"].last[:top_level]
137
+
138
+ assert_equal 4, job_chains["chain_a_b"].last[:jobs].length
139
+ assert_equal job, job_chains["chain_a_b"].last[:top_level]
140
+ end
141
+
142
+ def test_job_chains_double
143
+ job = TestWFD.job(:d1, nil)
144
+ job.recursive_clean
145
+
146
+ job_chains = Workflow::Orchestrator.job_chains(RULES, job)
147
+ job_chains = NamedArray.setup(job_chains, job_chains.collect{|n,i| n })
148
+
149
+ assert_equal 2, job_chains.select{|n,i| n == 'chain_a' }.length
150
+ assert_equal ["First c3", "Second c3"].sort, job_chains.
151
+ select{|n,i| n == 'chain_a' }.
152
+ collect{|n,i| i[:top_level].name }.sort
153
+
154
+ assert_equal 1, job_chains.select{|n,i| n == 'chain_d' }.length
155
+ end
156
+
157
+ def __test_benchmark
158
+
159
+ job = TestDeepWF.job(:suite, :size => 100)
160
+ job.recursive_clean
161
+
162
+ Misc.benchmark(10) do
163
+ Workflow::Orchestrator.job_chains(RULES, job)
164
+ end
165
+
166
+ end
167
+
168
+
169
+
170
+ end
171
+
@@ -0,0 +1,219 @@
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 TestOrchestrateRules < Test::Unit::TestCase
5
+
6
+ RULES = IndiferentHash.setup(YAML.load(<<-EOF))
7
+ ---
8
+ defaults:
9
+ queue: first_queue
10
+ time: 1h
11
+ log: 2
12
+ config_keys: key1 value1 token1
13
+ chains:
14
+ chain_a:
15
+ workflow: TestWFA
16
+ tasks: a1, a2, a3
17
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
18
+ chain_b:
19
+ workflow: TestWFB
20
+ tasks: b1, b2
21
+ chain_b2:
22
+ comment: This chain is not valid, it is missing a2
23
+ tasks: TestWFA#a1, TestWFA#a3, TestWFB#b1, TestWFB#b2
24
+ TestWFA:
25
+ defaults:
26
+ log: 4
27
+ config_keys: key4 value4 token4
28
+ a1:
29
+ cpus: 10
30
+ config_keys: key5 value5 token5
31
+ TestWFC:
32
+ defaults:
33
+ skip: true
34
+ log: 4
35
+ EOF
36
+
37
+ def test_defaults
38
+ rules = Workflow::Orchestrator.task_specific_rules RULES, "TestWFA", :a1
39
+ assert_equal "first_queue" , rules[:queue]
40
+ end
41
+
42
+
43
+ def test_task_options
44
+ rules = Workflow::Orchestrator.task_specific_rules RULES, "TestWFA", :a1
45
+ assert_equal 10, rules[:cpus]
46
+ assert_equal 4, rules[:log]
47
+ end
48
+
49
+ def test_skip
50
+ rules = Workflow::Orchestrator.task_specific_rules RULES, "TestWFC", :c1
51
+ assert rules[:skip]
52
+ end
53
+
54
+ def test_load_rules
55
+ rules1 =<<-EOF
56
+ defaults:
57
+ name: rules1
58
+ time: 1h
59
+ cpus: 2
60
+ Workflow:
61
+ defaults:
62
+ time: 1m
63
+ cpus: 4
64
+ Workflow3:
65
+ defaults:
66
+ time: 3m
67
+ EOF
68
+
69
+ rules2 =<<-EOF
70
+ defaults:
71
+ name: rules2
72
+ time: 2h
73
+ Workflow:
74
+ defaults:
75
+ time: 2m
76
+ Workflow2:
77
+ defaults:
78
+ time: 3m
79
+ EOF
80
+
81
+ TmpFile.with_file rules1 do |file1|
82
+ TmpFile.with_file rules2 do |file2|
83
+
84
+ rules = Workflow::Orchestrator.load_rules [file2, file1]
85
+
86
+ assert_equal 'rules2', rules[:defaults][:name]
87
+
88
+ assert_equal 2, rules[:defaults][:cpus]
89
+ assert_equal '2h', rules[:defaults][:time]
90
+
91
+ assert_equal 4, rules['Workflow'][:defaults][:cpus]
92
+ assert_equal '2m', rules["Workflow"][:defaults][:time]
93
+
94
+ assert_include rules, 'Workflow2'
95
+ assert_include rules, 'Workflow3'
96
+ end
97
+ end
98
+ end
99
+
100
+ def test_load_rules_config_keys
101
+ rules1 =<<-EOF
102
+ Workflow:
103
+ defaults:
104
+ time: 1h
105
+ cpus: 2
106
+ config_keys: cpus 4 loop
107
+ EOF
108
+
109
+ rules2 =<<-EOF
110
+ Workflow:
111
+ defaults:
112
+ time: 1h
113
+ cpus: 4
114
+ config_keys: mem high database
115
+ EOF
116
+
117
+ correct = YAML.load <<-EOF
118
+ ---
119
+ Workflow:
120
+ defaults:
121
+ time: 1h
122
+ cpus: 4
123
+ config_keys: cpus 4 loop,mem high database
124
+ EOF
125
+
126
+
127
+ TmpFile.with_file rules1 do |file1|
128
+ TmpFile.with_file rules2 do |file2|
129
+
130
+ rules = Workflow::Orchestrator.load_rules [file2, file1]
131
+ assert_equal correct, rules
132
+ end
133
+ end
134
+ end
135
+
136
+
137
+ def test_load_rules_config_keys_alt
138
+ rules1 =<<-EOF
139
+ Workflow:
140
+ defaults:
141
+ name: rules1
142
+ time: 1h
143
+ cpus: 2
144
+ config_keys:
145
+ - cpus 4 loop
146
+ - level warn log
147
+ EOF
148
+
149
+ rules2 =<<-EOF
150
+ Workflow:
151
+ defaults:
152
+ name: rules2
153
+ time: 1h
154
+ cpus: 4
155
+ config_keys:
156
+ - mem high database
157
+ EOF
158
+
159
+ correct = YAML.load <<-EOF
160
+ ---
161
+ Workflow:
162
+ defaults:
163
+ name: rules2
164
+ time: 1h
165
+ cpus: 4
166
+ config_keys: cpus 4 loop,level warn log,mem high database
167
+ EOF
168
+
169
+
170
+ TmpFile.with_file rules1 do |file1|
171
+ TmpFile.with_file rules2 do |file2|
172
+
173
+ rules = Workflow::Orchestrator.load_rules [file2, file1]
174
+ assert_equal correct, rules
175
+ end
176
+ end
177
+ end
178
+
179
+
180
+ def test_load_rules_import
181
+ rules1 =<<-EOF
182
+ Workflow:
183
+ defaults:
184
+ time: 1h
185
+ cpus: 2
186
+ config_keys: cpus 4 loop
187
+ EOF
188
+
189
+ rules2 =<<-EOF
190
+ Workflow:
191
+ defaults:
192
+ time: 1h
193
+ cpus: 2
194
+ config_keys: mem high database
195
+ EOF
196
+
197
+ correct = YAML.load <<-EOF
198
+ ---
199
+ Workflow:
200
+ defaults:
201
+ time: 1h
202
+ cpus: 2
203
+ config_keys: cpus 4 loop,mem high database
204
+ EOF
205
+
206
+
207
+ TmpFile.with_file rules1 do |file1|
208
+ TmpFile.with_file rules2 do |file2|
209
+ Open.open(file2, mode: 'a') do |f|
210
+ f.puts "import: #{file1}"
211
+ end
212
+
213
+ rules = Workflow::Orchestrator.load_rules file2
214
+ assert_equal correct, rules
215
+ end
216
+ end
217
+ end
218
+ end
219
+
@@ -0,0 +1,117 @@
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
+ module TestWFA
5
+ extend Workflow
6
+
7
+ task :a1 => :string do self.task_name.to_s end
8
+
9
+ dep :a1
10
+ task :a2 => :string do self.task_name.to_s end
11
+
12
+ dep :a2
13
+ task :a3 => :string do self.task_name.to_s end
14
+ end
15
+
16
+ module TestWFB
17
+ extend Workflow
18
+
19
+ dep TestWFA, :a2
20
+ task :b1 => :string do self.task_name.to_s end
21
+
22
+ dep :b1
23
+ task :b2 => :string do self.task_name.to_s end
24
+ end
25
+
26
+ module TestWFC
27
+ extend Workflow
28
+
29
+ dep TestWFA, :a1
30
+ dep_task :c1, TestWFB, :b2
31
+
32
+ task :c2 => :string do self.task_name.to_s end
33
+
34
+ dep :c1
35
+ dep :c2
36
+ task :c3 => :string do self.task_name.to_s end
37
+
38
+ dep_task :c4, TestWFC, :c3
39
+ end
40
+
41
+ module TestWFD
42
+ extend Workflow
43
+
44
+ dep TestWFC, :c3, :jobname => "First c3"
45
+ dep TestWFC, :c3, :jobname => "Second c3"
46
+ task :d1 => :string do self.task_name.to_s end
47
+ end
48
+
49
+ module TestDeepWF
50
+ extend Workflow
51
+
52
+ dep_task :deep1, TestWFD, :d1
53
+
54
+ input :size, :integer, "Number of dependencies", 100
55
+ dep :deep1 do |jobname,options|
56
+ options[:size].to_i.times.collect{|i|
57
+ {:jobname => "step-#{i}"}
58
+ }
59
+ end
60
+ task :suite => :array do
61
+ end
62
+ end
63
+
64
+ class TestWorkload < Test::Unit::TestCase
65
+
66
+ RULES = IndiferentHash.setup(YAML.load(<<-EOF))
67
+ ---
68
+ defaults:
69
+ queue: first_queue
70
+ time: 1h
71
+ log: 2
72
+ config_keys: key1 value1 token1
73
+ chains:
74
+ chain_a_b:
75
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1, TestWFA#a2
76
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
77
+ chain_a:
78
+ workflow: TestWFA
79
+ tasks: a1, a2, a3
80
+ config_keys: key2 value2 token2, key3 value3 token3.1 token3.2
81
+ chain_b:
82
+ workflow: TestWFB
83
+ tasks: b1, b2
84
+ chain_b2:
85
+ tasks: TestWFB#b1, TestWFB#b2, TestWFA#a1
86
+ chain_d:
87
+ tasks: TestWFD#d1, TestWFC#c1, TestWFC#c2, TestWFC#c3
88
+ TestWFA:
89
+ defaults:
90
+ log: 4
91
+ config_keys: key4 value4 token4
92
+ time: 10min
93
+ a1:
94
+ cpus: 10
95
+ config_keys: key5 value5 token5
96
+ TestWFC:
97
+ defaults:
98
+ skip: true
99
+ log: 4
100
+ time: 10s
101
+ EOF
102
+
103
+ def test_workload
104
+ job = TestWFC.job(:c4, nil)
105
+ job.recursive_clean
106
+
107
+ workload = Workflow::Orchestrator.job_workload(job)
108
+ assert_equal [], workload[job.step(:c2)]
109
+ assert workload.select{|job,deps| deps.include? job }.empty?
110
+ assert_include workload[job], job.dependencies.first
111
+
112
+ workload = Workflow::Orchestrator.job_workload([job])
113
+ assert_equal [], workload[job.step(:c2)]
114
+ assert workload.select{|job,deps| deps.include? job }.empty?
115
+ assert_include workload[job], job.dependencies.first
116
+ end
117
+ end
@@ -0,0 +1,31 @@
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
+ # Define a small workflow used by tests
5
+ module TestSchedWF
6
+ extend Workflow
7
+
8
+ task :a1 => :string do self.task_name.to_s end
9
+
10
+ dep :a1
11
+ task :b1 => :string do self.task_name.to_s end
12
+ end
13
+
14
+ class TestSchedulerJob < Test::Unit::TestCase
15
+ def test_basic_template
16
+ job = TestSchedWF.job(:b1, "TEST")
17
+ TmpFile.with_file do |batch_dir|
18
+ tpl = SchedulerJob.job_template(job, :batch_dir => batch_dir, :lua_modules => 'java')
19
+ assert_include tpl, 'module load java'
20
+ assert_include tpl, '#STEP_PATH'
21
+ end
22
+ end
23
+
24
+ def test_singularity
25
+ job = TestSchedWF.job(:b1, "TEST")
26
+ TmpFile.with_file do |batch_dir|
27
+ tpl = SchedulerJob.job_template(job, :batch_dir => batch_dir, :singularity => true, :singularity_img => '/tmp/img.sif')
28
+ assert_include tpl, 'singularity exec'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
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
+ # Define a small workflow used by tests
5
+ module TestSchedWF
6
+ extend Workflow
7
+
8
+ task :a1 => :string do self.task_name.to_s end
9
+
10
+ dep :a1
11
+ task :b1 => :string do self.task_name.to_s end
12
+ end
13
+
14
+ class TestSchedulerJobLSF < Test::Unit::TestCase
15
+ def test_basic_template
16
+ job = TestSchedWF.job(:b1, "TEST")
17
+ TmpFile.with_file do |batch_dir|
18
+ tpl = LSF.job_template(job, :batch_dir => batch_dir, :lua_modules => 'java')
19
+ assert_include tpl, 'module load java'
20
+ assert_include tpl, '#STEP_PATH'
21
+ assert_include tpl, '#BSUB'
22
+ end
23
+ end
24
+
25
+ def test_singularity
26
+ job = TestSchedWF.job(:b1, "TEST")
27
+ TmpFile.with_file do |batch_dir|
28
+ tpl = LSF.job_template(job, :batch_dir => batch_dir, :singularity => true, :singularity_img => '/tmp/img.sif')
29
+ assert_include tpl, 'singularity exec'
30
+ end
31
+ end
32
+ end