osc-machete 1.1.3
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/.gitignore +17 -0
- data/CHANGELOG.md +87 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +194 -0
- data/Rakefile +23 -0
- data/lib/osc/machete.rb +18 -0
- data/lib/osc/machete/job.rb +239 -0
- data/lib/osc/machete/job_dir.rb +56 -0
- data/lib/osc/machete/location.rb +91 -0
- data/lib/osc/machete/process.rb +32 -0
- data/lib/osc/machete/status.rb +190 -0
- data/lib/osc/machete/torque_helper.rb +190 -0
- data/lib/osc/machete/user.rb +72 -0
- data/lib/osc/machete/version.rb +6 -0
- data/osc-machete.gemspec +30 -0
- data/test/fixtures/app-params.yml +8 -0
- data/test/fixtures/app-template-rendered/job.sh +40 -0
- data/test/fixtures/app-template-rendered/params.yml +8 -0
- data/test/fixtures/app-template-rendered/test/job.sh +40 -0
- data/test/fixtures/app-template/job.sh.mustache +40 -0
- data/test/fixtures/app-template/params.yml.mustache +8 -0
- data/test/fixtures/app-template/test/job.sh.mustache +40 -0
- data/test/fixtures/oakley.sh +14 -0
- data/test/fixtures/quick.sh +14 -0
- data/test/fixtures/ruby.sh +14 -0
- data/test/test_job.rb +179 -0
- data/test/test_job_dir.rb +39 -0
- data/test/test_location.rb +97 -0
- data/test/test_status.rb +99 -0
- data/test/test_torque_helper.rb +209 -0
- data/test/test_torque_helper_live.rb +174 -0
- metadata +177 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'osc/machete'
|
3
|
+
|
4
|
+
class TestJobDir < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@data_root = Dir.mktmpdir
|
7
|
+
@parent = Pathname.new(@data_root).join("containers")
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
FileUtils.remove_entry @data_root
|
12
|
+
end
|
13
|
+
|
14
|
+
# test and verify if we create a JobDir helper
|
15
|
+
# with a parent directory that doesn't yet exist
|
16
|
+
# new_jobdir returns /path/to/parent/1
|
17
|
+
def test_job_dir_with_missing_parent_dir
|
18
|
+
dirhelper = OSC::Machete::JobDir.new(@parent)
|
19
|
+
|
20
|
+
assert_equal [], dirhelper.jobdirs
|
21
|
+
assert_equal [], dirhelper.targetdirs
|
22
|
+
assert_equal @parent.join("1"), dirhelper.new_jobdir
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_new_jobdir_succeeds_with_numbered_directories
|
26
|
+
FileUtils.mkdir_p @parent
|
27
|
+
|
28
|
+
# Initialize app directory with multiple jobs
|
29
|
+
# and a file with a larger number
|
30
|
+
Dir.mkdir("#{@parent}/1")
|
31
|
+
Dir.mkdir("#{@parent}/5")
|
32
|
+
FileUtils.touch("#{@parent}/8")
|
33
|
+
|
34
|
+
# Create unique directory
|
35
|
+
new_jobdir = OSC::Machete::JobDir.new(@parent).new_jobdir
|
36
|
+
Dir.mkdir(new_jobdir)
|
37
|
+
assert Dir.exists?("#{@parent}/9"), "Directory was not created: #{@parent}/9"
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'osc/machete'
|
3
|
+
|
4
|
+
class TestLocation < Minitest::Test
|
5
|
+
|
6
|
+
def setup
|
7
|
+
# tmp directory
|
8
|
+
# and we are making a location object that wraps that directory
|
9
|
+
# we add mustache templates and test rendering
|
10
|
+
# we add another tmp directory/location and we test copy to
|
11
|
+
@dir1 = Dir.mktmpdir("location")
|
12
|
+
@dir2 = Dir.mktmpdir("location")
|
13
|
+
@location1 = OSC::Machete::Location.new(@dir1)
|
14
|
+
@location2 = OSC::Machete::Location.new(@dir2)
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
FileUtils.remove_entry @dir1
|
19
|
+
FileUtils.remove_entry @dir2
|
20
|
+
end
|
21
|
+
|
22
|
+
# Location.render(params, options = {})
|
23
|
+
|
24
|
+
def test_render_default_replace_template
|
25
|
+
setup_render
|
26
|
+
@location1.render("")
|
27
|
+
assert_equal true, File.exists?("#{@dir1}/file.txt")
|
28
|
+
assert_equal false, File.exists?("#{@dir1}/file.txt.mustache")
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_render_user_replace_template
|
32
|
+
setup_render
|
33
|
+
@location1.render("", {replace: true})
|
34
|
+
assert_equal true, File.exists?("#{@dir1}/file.txt")
|
35
|
+
assert_equal false, File.exists?("#{@dir1}/file.txt.mustache")
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_render_user_doesnt_replace_template
|
39
|
+
setup_render
|
40
|
+
@location1.render("", {replace: false})
|
41
|
+
assert_equal true, File.exists?("#{@dir1}/file.txt")
|
42
|
+
assert_equal true, File.exists?("#{@dir1}/file.txt.mustache")
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_copy_to_shouldnt_copy_developer_files
|
46
|
+
setup_copy_to
|
47
|
+
|
48
|
+
@location1.copy_to(@dir2)
|
49
|
+
assert_equal true, Dir.exists?("#{@dir2}")
|
50
|
+
assert_equal false, Dir.exists?("#{@dir2}/.git")
|
51
|
+
assert_equal false, Dir.exists?("#{@dir2}/.svn")
|
52
|
+
assert_equal false, Dir.exists?("#{@dir2}/test.dir.1")
|
53
|
+
assert_equal true, Dir.exists?("#{@dir2}/test.dir.2")
|
54
|
+
assert_equal true, File.exists?("#{@dir2}/test.1")
|
55
|
+
assert_equal false, File.exists?("#{@dir2}/test.2")
|
56
|
+
assert_equal true, File.exists?("#{@dir2}/test.3")
|
57
|
+
assert_equal false, File.exists?("#{@dir2}/test.4")
|
58
|
+
assert_equal false, File.exists?("#{@dir2}/test.dir.2/test.1")
|
59
|
+
assert_equal false, File.exists?("#{@dir2}/test.dir.2/test.2")
|
60
|
+
assert_equal true, File.exists?("#{@dir2}/test.dir.2/test.4")
|
61
|
+
assert_equal false, File.exists?("#{@dir2}/.gitignore")
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def setup_render
|
68
|
+
FileUtils.touch("#{@dir1}/file.txt.mustache")
|
69
|
+
end
|
70
|
+
|
71
|
+
def setup_copy_to
|
72
|
+
# Example directory/file structure of developer
|
73
|
+
Dir.mkdir("#{@dir1}/.git")
|
74
|
+
Dir.mkdir("#{@dir1}/.svn")
|
75
|
+
Dir.mkdir("#{@dir1}/test.dir.1")
|
76
|
+
Dir.mkdir("#{@dir1}/test.dir.2")
|
77
|
+
FileUtils.touch("#{@dir1}/test.1")
|
78
|
+
FileUtils.touch("#{@dir1}/test.2")
|
79
|
+
FileUtils.touch("#{@dir1}/test.3")
|
80
|
+
FileUtils.touch("#{@dir1}/test.4")
|
81
|
+
FileUtils.touch("#{@dir1}/test.dir.2/test.1")
|
82
|
+
FileUtils.touch("#{@dir1}/test.dir.2/test.2")
|
83
|
+
FileUtils.touch("#{@dir1}/test.dir.2/test.4")
|
84
|
+
|
85
|
+
# Make example .gitignore
|
86
|
+
gitignore = <<-END.gsub(/^ {20}/, '')
|
87
|
+
# All files here will be ignored
|
88
|
+
test.2
|
89
|
+
#test.3
|
90
|
+
/test.4
|
91
|
+
test.dir.1
|
92
|
+
test.dir.2/test.1
|
93
|
+
END
|
94
|
+
|
95
|
+
File.open("#{@dir1}/.gitignore", 'w') {|f| f.write(gitignore) }
|
96
|
+
end
|
97
|
+
end
|
data/test/test_status.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'osc/machete'
|
3
|
+
|
4
|
+
class TestStatus < Minitest::Test
|
5
|
+
include OSC::Machete
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@passed = Status.passed
|
9
|
+
@running = Status.running
|
10
|
+
@held = Status.held
|
11
|
+
@queued = Status.queued
|
12
|
+
@failed = Status.failed
|
13
|
+
@new = Status.not_submitted
|
14
|
+
@suspended = Status.suspended
|
15
|
+
@undetermined = Status.undetermined
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_status_equality
|
22
|
+
assert Status.new(:F).eql?(Status.new("F"))
|
23
|
+
assert_equal Status.new(:F), Status.new("F")
|
24
|
+
assert_equal @failed, Status.new("F")
|
25
|
+
assert_equal @passed, Status.new("C")
|
26
|
+
|
27
|
+
#FIXME: is supporting comparisons between Status values and Strings a good idea?
|
28
|
+
assert_equal @passed, "C"
|
29
|
+
|
30
|
+
# default value is
|
31
|
+
assert_equal Status.new(""), @new
|
32
|
+
assert_equal Status.new(nil), @new
|
33
|
+
assert_nil @new.char
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_to_s
|
37
|
+
assert_equal "Passed", @passed.to_s
|
38
|
+
assert_equal "Not Submitted", @new.to_s
|
39
|
+
assert_equal "Running", @running.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_create_status_value_from_status_value
|
43
|
+
assert_equal @passed, OSC::Machete::Status.new(@passed)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_helpers
|
47
|
+
assert_equal false, @passed.active?
|
48
|
+
assert_equal true, @passed.completed?
|
49
|
+
assert_equal true, @passed.passed?
|
50
|
+
assert_equal true, @queued.queued?
|
51
|
+
assert_equal true, @queued.active?
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_max
|
55
|
+
assert_equal @passed, [@passed, @passed].max
|
56
|
+
assert_equal @passed, [@new, @passed].max
|
57
|
+
assert_equal @running, [@running, @queued].max
|
58
|
+
assert_equal @failed, [@passed, @failed].max
|
59
|
+
assert_equal @running, [@passed, @running].max
|
60
|
+
assert_equal @running, [@running, @queued].max
|
61
|
+
assert_equal @queued, [@new, @queued].max
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_add
|
65
|
+
assert_equal @passed, @passed + @passed
|
66
|
+
assert_equal @passed, @new + @passed
|
67
|
+
assert_equal @running, @running + @queued
|
68
|
+
assert_equal @failed, @passed + @failed
|
69
|
+
assert_equal @running, @passed + @running
|
70
|
+
assert_equal @running, @running + @queued
|
71
|
+
assert_equal @queued, @new + @queued
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_undetermined
|
75
|
+
assert_equal Status.new("X"), Status.undetermined
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_submitted
|
79
|
+
assert @passed.submitted?
|
80
|
+
assert @running.submitted?
|
81
|
+
assert @queued.submitted?
|
82
|
+
assert @failed.submitted?
|
83
|
+
assert @passed.submitted?
|
84
|
+
assert ! @new.submitted?
|
85
|
+
assert ! Status.undetermined.submitted?
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_active_status_values
|
89
|
+
assert_equal Status.values.sort, [@undetermined, @new, @passed, @failed, @held, @queued, @running, @suspended].sort
|
90
|
+
assert_equal Status.active_values.sort, [@running, @queued, @held, @suspended].sort
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_completed
|
94
|
+
assert_equal Status.completed_values.sort, [@passed, @failed]
|
95
|
+
assert @passed.completed?
|
96
|
+
assert @failed.completed?
|
97
|
+
assert ! @running.completed?
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'osc/machete'
|
3
|
+
require 'pbs'
|
4
|
+
require 'mocha/setup'
|
5
|
+
|
6
|
+
# test helper class
|
7
|
+
class TestTorqueHelper < Minitest::Test
|
8
|
+
|
9
|
+
# FIXME:
|
10
|
+
# will be replacing with programmatic access to torque
|
11
|
+
# however... we should have our tests actually submit tiny jobs on a queue that can respond immediately,
|
12
|
+
# run for a minute, and die
|
13
|
+
# perhaps using the Oxymoron cluster for this purpose?
|
14
|
+
#
|
15
|
+
# 2016/01/08 Implemented this in `test_qsub_oakley` and `test_qsub_ruby`. The test only runs when rake
|
16
|
+
# is called on the correct submit host. On all other systems, only the stubs are used.
|
17
|
+
|
18
|
+
def setup
|
19
|
+
# FIXME: Torque only works from websvsc02
|
20
|
+
# This raises an issue mentioning that it is not being submitted on the
|
21
|
+
# correct host, comment out the raise to skip the live tests.
|
22
|
+
# Maybe this would be better accomplished with a separate rake task.
|
23
|
+
@submit_host = "websvcs02.osc.edu"
|
24
|
+
|
25
|
+
@job_state_queued = OSC::Machete::Status.queued
|
26
|
+
@job_state_completed = OSC::Machete::Status.passed
|
27
|
+
@job_state_running = OSC::Machete::Status.running
|
28
|
+
@job_state_undetermined = OSC::Machete::Status.undetermined
|
29
|
+
|
30
|
+
@shell = OSC::Machete::TorqueHelper.new
|
31
|
+
|
32
|
+
# test staging using HSP template
|
33
|
+
#@params = YAML.load(File.read('test/fixtures/app-params.yml'))
|
34
|
+
#@template = 'test/fixtures/app-template'
|
35
|
+
#@expected = 'test/fixtures/app-template-rendered'
|
36
|
+
|
37
|
+
# directory where to create jobs
|
38
|
+
#@target = Dir.mktmpdir
|
39
|
+
#@script = 'GLO_job'
|
40
|
+
|
41
|
+
@script_oakley = 'test/fixtures/oakley.sh'
|
42
|
+
@script_ruby = 'test/fixtures/ruby.sh'
|
43
|
+
end
|
44
|
+
|
45
|
+
# FIXME: what is the purpose of these tests?
|
46
|
+
# # Test qstat parameters for completed job.
|
47
|
+
# def test_qsub_oakley_stub
|
48
|
+
# PBS::Job.any_instance.stubs(:submit).with(file: @script_oakley, headers: {}, qsub: true).returns(PBS::Job.new(conn: 'oakley', id: '1234598.oak-batch.osc.edu'))
|
49
|
+
# assert_equal "1234598.oak-batch.osc.edu", @shell.qsub(@script_oakley)
|
50
|
+
# PBS::Job.any_instance.unstub(:submit)
|
51
|
+
# end
|
52
|
+
|
53
|
+
# # Test job state parser when returning queued
|
54
|
+
# def test_qsub_ruby_stub
|
55
|
+
# PBS::Job.any_instance.stubs(:submit).with(file: @script_ruby, headers: {}, qsub: true).returns(PBS::Job.new(conn: 'ruby', id: '1234598'))
|
56
|
+
# assert_equal "1234598", @shell.qsub(@script_ruby)
|
57
|
+
# PBS::Job.any_instance.unstub(:submit)
|
58
|
+
# end
|
59
|
+
|
60
|
+
def test_qstat_state_no_job
|
61
|
+
PBS::Job.any_instance.stubs(:status).raises(PBS::UnkjobidError, "Unknown Job Id")
|
62
|
+
assert_equal @job_state_completed, @shell.qstat("")
|
63
|
+
assert_equal @job_state_completed, @shell.qstat(nil)
|
64
|
+
PBS::Job.any_instance.unstub(:status)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Test that qstat returns Running job StatusValue
|
68
|
+
def test_qstat_state_running_oakley
|
69
|
+
PBS::Job.any_instance.stubs(:status).returns({ :attribs => { :job_state => "R" }})
|
70
|
+
assert_equal @job_state_running, @shell.qstat("123.oak-batch.osc.edu")
|
71
|
+
PBS::Job.any_instance.unstub(:status)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Test that qstat returns Queued job StatusValue
|
75
|
+
def test_qstat_state_queued_oakley
|
76
|
+
PBS::Job.any_instance.stubs(:status).returns({ :attribs => { :job_state => "Q" }})
|
77
|
+
assert_equal @job_state_queued, @shell.qstat("123.oak-batch.osc.edu")
|
78
|
+
PBS::Job.any_instance.unstub(:status)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Test that qstat returns Queued job StatusValue
|
82
|
+
def test_qstat_state_running_ruby
|
83
|
+
PBS::Job.any_instance.stubs(:status).returns({ :attribs => { :job_state => "Q" }})
|
84
|
+
assert_equal @job_state_queued, @shell.qstat("12398765")
|
85
|
+
PBS::Job.any_instance.unstub(:status)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Test that qstat returns Completed job StatusValue when state is nil.
|
89
|
+
def test_qstat_state_completed_oakley
|
90
|
+
PBS::Job.any_instance.stubs(:status).raises(PBS::UnkjobidError, "Unknown Job Id Error")
|
91
|
+
assert_equal @job_state_completed, @shell.qstat("123.oak-batch.osc.edu")
|
92
|
+
PBS::Job.any_instance.unstub(:status)
|
93
|
+
|
94
|
+
PBS::Job.any_instance.stubs(:status).raises(PBS::UnkjobidError, "Unknown Job Id")
|
95
|
+
assert_equal @job_state_completed, @shell.qstat("123.oak-batch.osc.edu")
|
96
|
+
PBS::Job.any_instance.unstub(:status)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Test that qdel works for oakley
|
100
|
+
def test_qdel_oakley_ok
|
101
|
+
PBS::Job.any_instance.stubs(:delete).returns(true)
|
102
|
+
assert_equal true, @shell.qdel("123.oak-batch.osc.edu")
|
103
|
+
PBS::Job.any_instance.unstub(:delete)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Test that qdel works for quick batch
|
107
|
+
def test_qdel_quick
|
108
|
+
PBS::Job.any_instance.stubs(:delete).returns(true)
|
109
|
+
assert_equal true, @shell.qdel("123.quick-batch.osc.edu")
|
110
|
+
PBS::Job.any_instance.unstub(:delete)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Test that qdel works for Ruby cluster
|
114
|
+
def test_qdel_ruby
|
115
|
+
PBS::Job.any_instance.stubs(:delete).returns(true)
|
116
|
+
assert_equal true, @shell.qdel("12365478")
|
117
|
+
PBS::Job.any_instance.unstub(:delete)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Test that qdel throws exception on PBS exception
|
121
|
+
def test_qdel_throws_exception
|
122
|
+
PBS::Job.any_instance.stubs(:delete).raises(PBS::Error)
|
123
|
+
assert_raises(PBS::Error) { @shell.qdel("123.quick-batch.osc.edu") }
|
124
|
+
PBS::Job.any_instance.unstub(:delete)
|
125
|
+
|
126
|
+
PBS::Job.any_instance.stubs(:delete).raises(PBS::SystemError)
|
127
|
+
assert_raises(PBS::SystemError) { @shell.qdel("123.quick-batch.osc.edu") }
|
128
|
+
PBS::Job.any_instance.unstub(:delete)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Test that qdel doesn't throw exception if Unknown Job Id exception
|
132
|
+
def test_qdel_doesnt_throw_exception_on_unknown_job_id
|
133
|
+
PBS::Job.any_instance.stubs(:delete).raises(PBS::UnkjobidError)
|
134
|
+
@shell.qdel("123.quick-batch.osc.edu")
|
135
|
+
PBS::Job.any_instance.unstub(:delete)
|
136
|
+
end
|
137
|
+
|
138
|
+
def assert_qsub_dependency_list(dependency_list, dependencies, host=nil)
|
139
|
+
assert_equal dependency_list, @shell.qsub_dependencies_header(dependencies)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_qsub_afterany
|
143
|
+
assert_qsub_dependency_list("afterany:1234.oak-batch.osc.edu", { afterany: ["1234.oak-batch.osc.edu"] })
|
144
|
+
assert_qsub_dependency_list("afterany:1234.oakbatch.osc.edu", { afterany: "1234.oakbatch.osc.edu" })
|
145
|
+
assert_qsub_dependency_list("afterany:1234.oakbatch.osc.edu:2345.oakbatch.osc.edu", { afterany: ["1234.oakbatch.osc.edu", "2345.oakbatch.osc.edu"] })
|
146
|
+
return true
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def test_qsub_afterok
|
151
|
+
assert_qsub_dependency_list("afterok:1234.oakbatch.osc.edu", { afterok: ["1234.oakbatch.osc.edu"] })
|
152
|
+
assert_qsub_dependency_list("afterok:1234.oakbatch.osc.edu:2345.oakbatch.osc.edu", { afterok: ["1234.oakbatch.osc.edu", "2345.oakbatch.osc.edu"] })
|
153
|
+
return true
|
154
|
+
end
|
155
|
+
|
156
|
+
# With multiple dependency types, is formatted:
|
157
|
+
# type[:argument[:argument...][,type:argument...]
|
158
|
+
# i.e.
|
159
|
+
# -W depend=afterany:1234.oakbatch.osc.edu,afterok:2345.oakbatch.osc.edu"
|
160
|
+
#
|
161
|
+
# See qsub manpage for details
|
162
|
+
def test_qsub_afterok_and_afterany
|
163
|
+
assert_qsub_dependency_list("afterany:1234.oakbatch.osc.edu,afterok:2345.oakbatch.osc.edu", { afterany: "1234.oakbatch.osc.edu", afterok: "2345.oakbatch.osc.edu" } )
|
164
|
+
return true
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_qsub_other
|
168
|
+
assert_qsub_dependency_list("after:1234.oakbatch.osc.edu", { after: ["1234.oakbatch.osc.edu"] })
|
169
|
+
assert_qsub_dependency_list("afternotok:1234.oakbatch.osc.edu:2345.oakbatch.osc.edu", { afternotok: ["1234.oakbatch.osc.edu", "2345.oakbatch.osc.edu"] })
|
170
|
+
return true
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_qsub_all_dependencies
|
174
|
+
dependencies = {
|
175
|
+
afterany: "1234.oakbatch.osc.edu",
|
176
|
+
afterok: "2345.oakbatch.osc.edu",
|
177
|
+
after: ["2347.oakbatch.osc.edu", "2348.oakbatch.osc.edu"],
|
178
|
+
afternotok: ["2349.oakbatch.osc.edu", "2350.oakbatch.osc.edu", "2351.oakbatch.osc.edu"]
|
179
|
+
}
|
180
|
+
|
181
|
+
depencencies_str = "afterany:1234.oakbatch.osc.edu"
|
182
|
+
depencencies_str += ",afterok:2345.oakbatch.osc.edu"
|
183
|
+
depencencies_str += ",after:2347.oakbatch.osc.edu:2348.oakbatch.osc.edu"
|
184
|
+
depencencies_str += ",afternotok:2349.oakbatch.osc.edu:2350.oakbatch.osc.edu:2351.oakbatch.osc.edu"
|
185
|
+
|
186
|
+
assert_qsub_dependency_list(depencencies_str, dependencies)
|
187
|
+
return true
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_account_string_passed_into_qsub_used_during_submit_call
|
191
|
+
PBS::Job.any_instance.expects(:submit).with(has_entry(headers: {Account_Name: "XXX"})).returns(PBS::Job.new(conn: 'oakley', id: '1234598.oak-batch.osc.edu'))
|
192
|
+
@shell.qsub(@script_oakley, account_string: "XXX")
|
193
|
+
PBS::Job.any_instance.unstub(:submit)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_default_account_string_used_in_qsub_during_submit_call
|
197
|
+
@shell.stubs(:default_account_string).returns("PZS3000")
|
198
|
+
|
199
|
+
PBS::Job.any_instance.expects(:submit).with(has_entry(headers: {Account_Name: @shell.default_account_string})).returns(PBS::Job.new(conn: 'oakley', id: '1234598.oak-batch.osc.edu'))
|
200
|
+
@shell.qsub(@script_oakley)
|
201
|
+
|
202
|
+
@shell.stubs(:default_account_string).returns("appl")
|
203
|
+
PBS::Job.any_instance.expects(:submit).with(has_entry(headers: {})).returns(PBS::Job.new(conn: 'oakley', id: '1234598.oak-batch.osc.edu'))
|
204
|
+
@shell.qsub(@script_oakley)
|
205
|
+
|
206
|
+
PBS::Job.any_instance.unstub(:submit)
|
207
|
+
@shell.unstub(:default_account_string)
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'osc/machete'
|
3
|
+
require 'pbs'
|
4
|
+
require 'mocha/setup'
|
5
|
+
|
6
|
+
# test helper class
|
7
|
+
class TestTorqueHelperLive < Minitest::Test
|
8
|
+
|
9
|
+
# FIXME:
|
10
|
+
# All of our tests here are broken after updating to PBS
|
11
|
+
# Everything will need to be revisited.
|
12
|
+
|
13
|
+
# FIXME:
|
14
|
+
# will be replacing with programmatic access to torque
|
15
|
+
# however... we should have our tests actually submit tiny jobs on a queue that can respond immediately,
|
16
|
+
# run for a minute, and die
|
17
|
+
# perhaps using the Oxymoron cluster for this purpose?
|
18
|
+
#
|
19
|
+
# 2016/01/08 Implemented this in `test_qsub_oakley` and `test_qsub_ruby`. The test only runs when rake
|
20
|
+
# is called on the correct submit host. On all other systems, only the stubs are used.
|
21
|
+
#
|
22
|
+
def live_test_enabled?
|
23
|
+
! ENV['LIVETEST'].nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup
|
27
|
+
|
28
|
+
# FIXME: Torque only works from websvsc02
|
29
|
+
# This raises an issue mentioning that it is not being submitted on the
|
30
|
+
# correct host, comment out the raise to skip the live tests.
|
31
|
+
# Maybe this would be better accomplished with a separate rake task.
|
32
|
+
@submit_host = "websvcs02.osc.edu"
|
33
|
+
|
34
|
+
@job_state_queued = OSC::Machete::Status.queued
|
35
|
+
@job_state_completed = OSC::Machete::Status.passed
|
36
|
+
@job_state_running = OSC::Machete::Status.running
|
37
|
+
|
38
|
+
@shell = OSC::Machete::TorqueHelper.new
|
39
|
+
|
40
|
+
# test staging using HSP template
|
41
|
+
#@params = YAML.load(File.read('test/fixtures/app-params.yml'))
|
42
|
+
#@template = 'test/fixtures/app-template'
|
43
|
+
#@expected = 'test/fixtures/app-template-rendered'
|
44
|
+
|
45
|
+
# directory where to create jobs
|
46
|
+
#@target = Dir.mktmpdir
|
47
|
+
#@script = 'GLO_job'
|
48
|
+
|
49
|
+
@script_oakley = 'test/fixtures/oakley.sh'
|
50
|
+
@script_ruby = 'test/fixtures/ruby.sh'
|
51
|
+
@script_quick = 'test/fixtures/quick.sh'
|
52
|
+
end
|
53
|
+
|
54
|
+
# This tests an actual live workflow by
|
55
|
+
# submitting a job to oakley,
|
56
|
+
# checking it's status, and
|
57
|
+
# deleting it.
|
58
|
+
#
|
59
|
+
# Only works on the current submit host.
|
60
|
+
def test_qsub_oakley
|
61
|
+
return unless live_test_enabled?
|
62
|
+
|
63
|
+
torque = OSC::Machete::TorqueHelper.new
|
64
|
+
|
65
|
+
# Don't run the tests if the host doesn't match.
|
66
|
+
if Socket.gethostname == @submit_host
|
67
|
+
# Submit a small job.
|
68
|
+
live_job = torque.qsub(@script_oakley)
|
69
|
+
assert_match(/\d+.oak-batch.osc.edu/, live_job)
|
70
|
+
|
71
|
+
# Qstat it to make sure it's queued.
|
72
|
+
live_status = torque.qstat(live_job)
|
73
|
+
assert_equal @job_state_queued, live_status
|
74
|
+
|
75
|
+
# Delete it and assert true returned.
|
76
|
+
live_delete_status = torque.qdel(live_job)
|
77
|
+
assert_equal nil, live_delete_status
|
78
|
+
else
|
79
|
+
puts "Run test 'test_qsub_oakley' on the batch system from #{@submit_host}."
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# This tests an actual live workflow by
|
85
|
+
# submitting a job to ruby with an oakley script,
|
86
|
+
# checking it's status, and
|
87
|
+
# deleting it.
|
88
|
+
#
|
89
|
+
# Only works on the current submit host.
|
90
|
+
def test_qsub_ruby_with_oakley_script
|
91
|
+
return unless live_test_enabled?
|
92
|
+
|
93
|
+
torque = OSC::Machete::TorqueHelper.new
|
94
|
+
|
95
|
+
# Don't run the tests if the host doesn't match.
|
96
|
+
if Socket.gethostname == @submit_host
|
97
|
+
# Submit a small job to ruby using an Oakley script,
|
98
|
+
# ensuring that we are no longer evaluating the headers.
|
99
|
+
live_job = torque.qsub(@script_oakley, host: "ruby")
|
100
|
+
assert_match(/\d+$/, live_job)
|
101
|
+
|
102
|
+
# Qstat it to make sure it's queued.
|
103
|
+
live_status = torque.qstat(live_job)
|
104
|
+
assert_equal @job_state_queued, live_status
|
105
|
+
|
106
|
+
# Delete it and assert true returned.
|
107
|
+
live_delete_status = torque.qdel(live_job)
|
108
|
+
assert_equal nil, live_delete_status
|
109
|
+
else
|
110
|
+
puts "Run test 'test_qsub_ruby_with_oakley_script' on the batch system from #{@submit_host}."
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
# This tests an actual live workflow by
|
116
|
+
# submitting a job to ruby,
|
117
|
+
# checking it's status, and
|
118
|
+
# deleting it.
|
119
|
+
#
|
120
|
+
# Only works on the current submit host.
|
121
|
+
def test_qsub_ruby
|
122
|
+
return unless live_test_enabled?
|
123
|
+
|
124
|
+
torque = OSC::Machete::TorqueHelper.new
|
125
|
+
|
126
|
+
# Don't run the tests if the host doesn't match.
|
127
|
+
if Socket.gethostname == @submit_host
|
128
|
+
# Submit a small job.
|
129
|
+
live_job = torque.qsub(@script_ruby)
|
130
|
+
assert_match /^\d+$/, live_job
|
131
|
+
|
132
|
+
# Qstat it to make sure it's queued.
|
133
|
+
live_status = torque.qstat(live_job)
|
134
|
+
assert_equal @job_state_queued, live_status
|
135
|
+
|
136
|
+
# Delete it and assert true returned.
|
137
|
+
live_delete_status = torque.qdel(live_job)
|
138
|
+
assert_equal nil, live_delete_status
|
139
|
+
else
|
140
|
+
puts "Run test 'test_qsub_ruby' on the batch system from #{@submit_host}."
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# This tests an actual live workflow by
|
145
|
+
# submitting a job to quick,
|
146
|
+
# checking it's status, and
|
147
|
+
# deleting it.
|
148
|
+
#
|
149
|
+
# Only works on the current submit host.
|
150
|
+
def test_qsub_quick
|
151
|
+
return unless live_test_enabled?
|
152
|
+
|
153
|
+
torque = OSC::Machete::TorqueHelper.new
|
154
|
+
|
155
|
+
# Don't run the tests if the host doesn't match.
|
156
|
+
if Socket.gethostname == @submit_host
|
157
|
+
# Submit a small job.
|
158
|
+
live_job = torque.qsub(@script_quick, host: 'quick')
|
159
|
+
assert_match /\d+.quick-batch.osc.edu/, live_job
|
160
|
+
|
161
|
+
# Qstat it to make sure it's queued.
|
162
|
+
live_status = torque.qstat(live_job)
|
163
|
+
assert_equal @job_state_queued, live_status
|
164
|
+
|
165
|
+
# Delete it and assert true returned.
|
166
|
+
live_delete_status = torque.qdel(live_job)
|
167
|
+
assert_equal nil, live_delete_status
|
168
|
+
else
|
169
|
+
puts "Run test 'test_qsub_quick' on the batch system from #{@submit_host}."
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
end
|