osc_machete_rails 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +76 -0
- data/LICENSE.txt +22 -0
- data/README.md +14 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/osc_machete_rails/application.js +13 -0
- data/app/assets/stylesheets/osc_machete_rails/application.css +13 -0
- data/app/controllers/osc_machete_rails/application_controller.rb +4 -0
- data/app/helpers/osc_machete_rails/application_helper.rb +4 -0
- data/app/views/layouts/osc_machete_rails/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/lib/generators/active_record/job_model_generator.rb +13 -0
- data/lib/generators/active_record/orm_helpers.rb +6 -0
- data/lib/generators/active_record/templates/job_model.rb +17 -0
- data/lib/generators/active_record/templates/migration.rb +19 -0
- data/lib/generators/active_record/templates/module.rb +7 -0
- data/lib/generators/active_record/templates/workflow_model.rb +34 -0
- data/lib/generators/active_record/workflow_model_generator.rb +30 -0
- data/lib/generators/osc_machete_rails/USAGE +36 -0
- data/lib/generators/osc_machete_rails/erb/erb_generator.rb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/_form.html.erb +21 -0
- data/lib/generators/osc_machete_rails/erb/templates/edit.html.erb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/index.html.erb +41 -0
- data/lib/generators/osc_machete_rails/erb/templates/new.html.erb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/show.html.erb +13 -0
- data/lib/generators/osc_machete_rails/job_helpers.rb +10 -0
- data/lib/generators/osc_machete_rails/job_model/USAGE +28 -0
- data/lib/generators/osc_machete_rails/job_model/job_model_generator.rb +13 -0
- data/lib/generators/osc_machete_rails/resource_route/USAGE +3 -0
- data/lib/generators/osc_machete_rails/resource_route/resource_route_generator.rb +57 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/USAGE +17 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/scaffold_controller_generator.rb +24 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/templates/controller.rb +120 -0
- data/lib/generators/osc_machete_rails/scaffold_generator.rb +35 -0
- data/lib/generators/osc_machete_rails/workflow_model/USAGE +38 -0
- data/lib/generators/osc_machete_rails/workflow_model/workflow_model_generator.rb +12 -0
- data/lib/generators/osc_machete_rails/workflow_template/USAGE +19 -0
- data/lib/generators/osc_machete_rails/workflow_template/templates/main.sh.mustache +18 -0
- data/lib/generators/osc_machete_rails/workflow_template/workflow_template_generator.rb +9 -0
- data/lib/osc_machete_rails/engine.rb +24 -0
- data/lib/osc_machete_rails/helper.rb +25 -0
- data/lib/osc_machete_rails/statusable.rb +199 -0
- data/lib/osc_machete_rails/version.rb +3 -0
- data/lib/osc_machete_rails/workflow.rb +249 -0
- data/lib/osc_machete_rails.rb +12 -0
- data/lib/tasks/osc_machete_rails_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/javascripts/simulations.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/simulations.css +4 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/simulations_controller.rb +103 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/simulations_helper.rb +2 -0
- data/test/dummy/app/models/simulation.rb +26 -0
- data/test/dummy/app/models/simulation_job.rb +15 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/simulations/_form.html.erb +15 -0
- data/test/dummy/app/views/simulations/edit.html.erb +5 -0
- data/test/dummy/app/views/simulations/index.html.erb +35 -0
- data/test/dummy/app/views/simulations/new.html.erb +5 -0
- data/test/dummy/app/views/simulations/show.html.erb +16 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +11 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20151230193910_create_simulations.rb +11 -0
- data/test/dummy/db/migrate/20151230193911_create_simulation_jobs.rb +15 -0
- data/test/dummy/db/schema.rb +38 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/jobs/simulation/main.sh.mustache +17 -0
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/log/test.log +31198 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0ff4cb4a6c217771a1336b307c51cf4e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/57261b7c75c19be33229517e39e47528 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9e1e594361ba2561e5f6011db99503bb +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/dc292ec300d07016ebcc2de4806208c3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/integration/error_handling_test.rb +166 -0
- data/test/integration/statusable_update_status_test.rb +47 -0
- data/test/models/simulation_test.rb +4 -0
- data/test/osc_machete_rails_test.rb +7 -0
- data/test/test_helper.rb +19 -0
- data/test/unit/statusable_test.rb +124 -0
- metadata +320 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
background-color: #EFEFEF;
|
|
8
|
+
color: #2E2F30;
|
|
9
|
+
text-align: center;
|
|
10
|
+
font-family: arial, sans-serif;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
div.dialog {
|
|
14
|
+
width: 25em;
|
|
15
|
+
margin: 4em auto 0 auto;
|
|
16
|
+
border: 1px solid #CCC;
|
|
17
|
+
border-right-color: #999;
|
|
18
|
+
border-left-color: #999;
|
|
19
|
+
border-bottom-color: #BBB;
|
|
20
|
+
border-top: #B00100 solid 4px;
|
|
21
|
+
border-top-left-radius: 9px;
|
|
22
|
+
border-top-right-radius: 9px;
|
|
23
|
+
background-color: white;
|
|
24
|
+
padding: 7px 4em 0 4em;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
h1 {
|
|
28
|
+
font-size: 100%;
|
|
29
|
+
color: #730E15;
|
|
30
|
+
line-height: 1.5em;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
body > p {
|
|
34
|
+
width: 33em;
|
|
35
|
+
margin: 0 auto 1em;
|
|
36
|
+
padding: 1em 0;
|
|
37
|
+
background-color: #F7F7F7;
|
|
38
|
+
border: 1px solid #CCC;
|
|
39
|
+
border-right-color: #999;
|
|
40
|
+
border-bottom-color: #999;
|
|
41
|
+
border-bottom-left-radius: 4px;
|
|
42
|
+
border-bottom-right-radius: 4px;
|
|
43
|
+
border-top-color: #DADADA;
|
|
44
|
+
color: #666;
|
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
</head>
|
|
49
|
+
|
|
50
|
+
<body>
|
|
51
|
+
<!-- This file lives in public/404.html -->
|
|
52
|
+
<div class="dialog">
|
|
53
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
|
54
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
|
55
|
+
</div>
|
|
56
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
background-color: #EFEFEF;
|
|
8
|
+
color: #2E2F30;
|
|
9
|
+
text-align: center;
|
|
10
|
+
font-family: arial, sans-serif;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
div.dialog {
|
|
14
|
+
width: 25em;
|
|
15
|
+
margin: 4em auto 0 auto;
|
|
16
|
+
border: 1px solid #CCC;
|
|
17
|
+
border-right-color: #999;
|
|
18
|
+
border-left-color: #999;
|
|
19
|
+
border-bottom-color: #BBB;
|
|
20
|
+
border-top: #B00100 solid 4px;
|
|
21
|
+
border-top-left-radius: 9px;
|
|
22
|
+
border-top-right-radius: 9px;
|
|
23
|
+
background-color: white;
|
|
24
|
+
padding: 7px 4em 0 4em;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
h1 {
|
|
28
|
+
font-size: 100%;
|
|
29
|
+
color: #730E15;
|
|
30
|
+
line-height: 1.5em;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
body > p {
|
|
34
|
+
width: 33em;
|
|
35
|
+
margin: 0 auto 1em;
|
|
36
|
+
padding: 1em 0;
|
|
37
|
+
background-color: #F7F7F7;
|
|
38
|
+
border: 1px solid #CCC;
|
|
39
|
+
border-right-color: #999;
|
|
40
|
+
border-bottom-color: #999;
|
|
41
|
+
border-bottom-left-radius: 4px;
|
|
42
|
+
border-bottom-right-radius: 4px;
|
|
43
|
+
border-top-color: #DADADA;
|
|
44
|
+
color: #666;
|
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
</head>
|
|
49
|
+
|
|
50
|
+
<body>
|
|
51
|
+
<!-- This file lives in public/422.html -->
|
|
52
|
+
<div class="dialog">
|
|
53
|
+
<h1>The change you wanted was rejected.</h1>
|
|
54
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
|
55
|
+
</div>
|
|
56
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
background-color: #EFEFEF;
|
|
8
|
+
color: #2E2F30;
|
|
9
|
+
text-align: center;
|
|
10
|
+
font-family: arial, sans-serif;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
div.dialog {
|
|
14
|
+
width: 25em;
|
|
15
|
+
margin: 4em auto 0 auto;
|
|
16
|
+
border: 1px solid #CCC;
|
|
17
|
+
border-right-color: #999;
|
|
18
|
+
border-left-color: #999;
|
|
19
|
+
border-bottom-color: #BBB;
|
|
20
|
+
border-top: #B00100 solid 4px;
|
|
21
|
+
border-top-left-radius: 9px;
|
|
22
|
+
border-top-right-radius: 9px;
|
|
23
|
+
background-color: white;
|
|
24
|
+
padding: 7px 4em 0 4em;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
h1 {
|
|
28
|
+
font-size: 100%;
|
|
29
|
+
color: #730E15;
|
|
30
|
+
line-height: 1.5em;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
body > p {
|
|
34
|
+
width: 33em;
|
|
35
|
+
margin: 0 auto 1em;
|
|
36
|
+
padding: 1em 0;
|
|
37
|
+
background-color: #F7F7F7;
|
|
38
|
+
border: 1px solid #CCC;
|
|
39
|
+
border-right-color: #999;
|
|
40
|
+
border-bottom-color: #999;
|
|
41
|
+
border-bottom-left-radius: 4px;
|
|
42
|
+
border-bottom-right-radius: 4px;
|
|
43
|
+
border-top-color: #DADADA;
|
|
44
|
+
color: #666;
|
|
45
|
+
box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
</head>
|
|
49
|
+
|
|
50
|
+
<body>
|
|
51
|
+
<!-- This file lives in public/500.html -->
|
|
52
|
+
<div class="dialog">
|
|
53
|
+
<h1>We're sorry, but something went wrong.</h1>
|
|
54
|
+
</div>
|
|
55
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
File without changes
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class ErrorHandlingTest < ActionDispatch::IntegrationTest
|
|
4
|
+
|
|
5
|
+
# these tests are for
|
|
6
|
+
|
|
7
|
+
def setup
|
|
8
|
+
setup_torquehelper
|
|
9
|
+
|
|
10
|
+
# FIXME: better to create simulations from doing a request to post a new sim
|
|
11
|
+
@sim = Simulation.create
|
|
12
|
+
@tmpdir = Dir.mktmpdir
|
|
13
|
+
@empty_template = Pathname.new(@tmpdir + "/template")
|
|
14
|
+
FileUtils.mkdir(@empty_template.to_s)
|
|
15
|
+
@empty_template = @empty_template.realpath
|
|
16
|
+
|
|
17
|
+
# so Workflow#ood_dataroot is set
|
|
18
|
+
ENV['OOD_DATAROOT'] = @tmpdir
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def setup_torquehelper
|
|
22
|
+
# defaults
|
|
23
|
+
OSC::Machete::TorqueHelper.any_instance.unstub(:qstat)
|
|
24
|
+
OSC::Machete::TorqueHelper.any_instance.unstub(:qdel)
|
|
25
|
+
OSC::Machete::TorqueHelper.any_instance.unstub(:qsub)
|
|
26
|
+
|
|
27
|
+
# use subclasses of PBS::Error
|
|
28
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).raises(PBS::SystemError, "The system is down!")
|
|
29
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qdel).raises(PBS::BadhostError, "The system is down!")
|
|
30
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qsub).raises(PBS::BadatvalError, "The system is down!")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def teardown
|
|
34
|
+
@sim.delete
|
|
35
|
+
FileUtils.rm_rf @tmpdir
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def simulations_dir_empty?
|
|
39
|
+
Dir[@tmpdir+'/*'].empty? || Dir[@tmpdir+'/simulations/*'].empty?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_handle_missing_script_error_on_submit
|
|
43
|
+
# stub to an empty template to trigger ScriptMissingError
|
|
44
|
+
Simulation.any_instance.stubs(:staging_template_dir).returns(@empty_template)
|
|
45
|
+
|
|
46
|
+
# sanity check
|
|
47
|
+
assert_equal 1, Simulation.count, "Sanity check failed"
|
|
48
|
+
assert simulations_dir_empty?, "Sanity check failed"
|
|
49
|
+
assert @empty_template.directory?, "Sanity check failed"
|
|
50
|
+
|
|
51
|
+
# now we should be able to try to submit the simulation, that needs main.sh but doesn't have it
|
|
52
|
+
put "/simulations/#{@sim.id}/submit"
|
|
53
|
+
|
|
54
|
+
assert_response 500
|
|
55
|
+
|
|
56
|
+
# verify an error message was attached to the simulation object
|
|
57
|
+
assert assigns(:simulation).errors.to_a.any?
|
|
58
|
+
assert assigns(:simulation).errors.to_a.first =~ /ScriptMissingError/, "Should have thrown ScriptMissingError"
|
|
59
|
+
assert simulations_dir_empty?, 'If submitting a simulation fails, the staged directory should be deleted.'
|
|
60
|
+
|
|
61
|
+
Simulation.any_instance.unstub(:staging_template_dir)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_handle_pbs_error_on_submit
|
|
65
|
+
# sanity check
|
|
66
|
+
assert_equal 1, Simulation.count, "Sanity check failed"
|
|
67
|
+
assert simulations_dir_empty?, "Sanity check failed"
|
|
68
|
+
|
|
69
|
+
# now we should be able to try to submit a simulation
|
|
70
|
+
put "/simulations/#{@sim.id}/submit"
|
|
71
|
+
|
|
72
|
+
assert_response 500
|
|
73
|
+
|
|
74
|
+
# verify an error message was attached to the simulation object
|
|
75
|
+
assert assigns(:simulation).errors.to_a.any?
|
|
76
|
+
assert assigns(:simulation).errors.to_a.first =~ /PBS::Error/, "Should have thrown PBS::Error"
|
|
77
|
+
assert simulations_dir_empty?, 'If submitting a simulation fails, the staged directory should be deleted.'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_handle_qstat_error_on_submit
|
|
81
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qsub).returns("123456.oakley.osc.edu")
|
|
82
|
+
|
|
83
|
+
put "/simulations/#{@sim.id}/submit"
|
|
84
|
+
|
|
85
|
+
assert_response :found
|
|
86
|
+
|
|
87
|
+
# submission succeeded, but qdel failed!
|
|
88
|
+
assert Simulation.find(@sim.id).status.queued?
|
|
89
|
+
assert Simulation.find(@sim.id).simulation_jobs.count == 1
|
|
90
|
+
|
|
91
|
+
# reset
|
|
92
|
+
setup_torquehelper
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_update_status_handles_qstat_error
|
|
97
|
+
@s1 = SimulationJob.create status: OSC::Machete::Status.queued, pbsid: "1"
|
|
98
|
+
@s2 = SimulationJob.create status: OSC::Machete::Status.queued, pbsid: "2"
|
|
99
|
+
@s3 = SimulationJob.create status: OSC::Machete::Status.queued, pbsid: "3"
|
|
100
|
+
|
|
101
|
+
# new
|
|
102
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).with("1", any_parameters).returns(OSC::Machete::Status.running)
|
|
103
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).with("2", any_parameters).raises(PBS::Error, "The system is down!")
|
|
104
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).with("3", any_parameters).returns(OSC::Machete::Status.passed)
|
|
105
|
+
|
|
106
|
+
get "/simulations"
|
|
107
|
+
|
|
108
|
+
# @s2 is queued and qstat will throw an error so it should just stay queued
|
|
109
|
+
# the others should be updated
|
|
110
|
+
assert_equal OSC::Machete::Status.running, SimulationJob.find(@s1.id).status
|
|
111
|
+
assert_equal OSC::Machete::Status.queued, SimulationJob.find(@s2.id).status
|
|
112
|
+
assert_equal OSC::Machete::Status.passed, SimulationJob.find(@s3.id).status
|
|
113
|
+
|
|
114
|
+
@s1.delete
|
|
115
|
+
@s2.delete
|
|
116
|
+
@s3.delete
|
|
117
|
+
|
|
118
|
+
# reset
|
|
119
|
+
setup_torquehelper
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_delete_running_simulation_fails
|
|
124
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qsub).returns("123456.oakley.osc.edu")
|
|
125
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).returns(OSC::Machete::Status.running)
|
|
126
|
+
|
|
127
|
+
put "/simulations/#{@sim.id}/submit"
|
|
128
|
+
|
|
129
|
+
assert_response :found
|
|
130
|
+
|
|
131
|
+
# verify we its running now
|
|
132
|
+
assert Simulation.find(@sim.id).status.running?
|
|
133
|
+
assert Simulation.find(@sim.id).simulation_jobs.count == 1
|
|
134
|
+
|
|
135
|
+
@job = @sim.simulation_jobs.first
|
|
136
|
+
|
|
137
|
+
# delete a running simulation
|
|
138
|
+
delete "/simulations/#{@sim.id}"
|
|
139
|
+
|
|
140
|
+
# delete threw error, so nothing should have happened
|
|
141
|
+
assert SimulationJob.find(@job.id).status.running?
|
|
142
|
+
assert Simulation.find(@sim.id).status.running?
|
|
143
|
+
assert Simulation.find(@sim.id).simulation_jobs.count == 1
|
|
144
|
+
|
|
145
|
+
assert_response 500
|
|
146
|
+
|
|
147
|
+
# verify an error message was attached to the simulation object
|
|
148
|
+
assert assigns(:simulation).errors.to_a.any?
|
|
149
|
+
assert assigns(:simulation).errors.to_a.first =~ /PBS::Error/, "Should have thrown PBS::Error"
|
|
150
|
+
|
|
151
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qdel).returns(nil)
|
|
152
|
+
|
|
153
|
+
# delete simulation now that "the system is fixed"
|
|
154
|
+
delete "/simulations/#{@sim.id}"
|
|
155
|
+
|
|
156
|
+
# delete threw error, so nothing should have happened
|
|
157
|
+
assert ! SimulationJob.where(id: @job.id).any?
|
|
158
|
+
assert ! Simulation.where(id: @sim.id).any?
|
|
159
|
+
|
|
160
|
+
assert_response :found
|
|
161
|
+
|
|
162
|
+
# reset
|
|
163
|
+
setup_torquehelper
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class StatusableUpdateStatusTest < ActionDispatch::IntegrationTest
|
|
4
|
+
fixtures :all
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
# FIXME: better to create simulations from doing a request to post a new sim
|
|
8
|
+
@sims = []
|
|
9
|
+
@sims << SimulationJob.create(status: OSC::Machete::Status.passed, pbsid: "123")
|
|
10
|
+
@sims << SimulationJob.create(status: OSC::Machete::Status.not_submitted, pbsid: "124")
|
|
11
|
+
@sims << SimulationJob.create(status: OSC::Machete::Status.queued, pbsid: "125")
|
|
12
|
+
@sims << SimulationJob.create(status: OSC::Machete::Status.running, pbsid: "126")
|
|
13
|
+
@sims << SimulationJob.create(status: OSC::Machete::Status.queued, pbsid: "127")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def teardown
|
|
17
|
+
# delete will avoid calling the destroy callbacks like "stop" i.e. qdel
|
|
18
|
+
@sims.each(&:delete)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_update_models_on_index_request
|
|
22
|
+
# 1. setup database and torque helper with jobs so that two jobs that are
|
|
23
|
+
# cached as queued and running are actually running and passed
|
|
24
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).returns(OSC::Machete::Status.passed)
|
|
25
|
+
|
|
26
|
+
# if a test below suddenly returns "Passed" instead of running it might be
|
|
27
|
+
# because the signature of qstat or the arguments Job#status is passing to
|
|
28
|
+
# these by default are different.
|
|
29
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).with("125", any_parameters).returns(OSC::Machete::Status.running)
|
|
30
|
+
OSC::Machete::TorqueHelper.any_instance.stubs(:qstat).with("127", any_parameters).returns(OSC::Machete::Status.queued)
|
|
31
|
+
|
|
32
|
+
# FIXME: move to a controller test?
|
|
33
|
+
assert_equal @sims.length, SimulationJob.count, "Test database is not cleaned up after each test is run"
|
|
34
|
+
|
|
35
|
+
# 2. when doing a get request, the active jobs should be updated
|
|
36
|
+
get "/simulations"
|
|
37
|
+
assert_response :success
|
|
38
|
+
|
|
39
|
+
# 3. we verify the modifications to the active jobs took place
|
|
40
|
+
assert_equal OSC::Machete::Status.passed, SimulationJob.where(pbsid: "123").first.status
|
|
41
|
+
assert_equal OSC::Machete::Status.not_submitted, SimulationJob.where(pbsid: "124").first.status
|
|
42
|
+
assert_equal OSC::Machete::Status.running, SimulationJob.where(pbsid: "125").first.status
|
|
43
|
+
assert_equal OSC::Machete::Status.passed, SimulationJob.where(pbsid: "126").first.status
|
|
44
|
+
assert_equal OSC::Machete::Status.queued, SimulationJob.where(pbsid: "127").first.status
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Configure Rails Environment
|
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
|
3
|
+
ENV["RAILS_DATAROOT"] = "/dev/null"
|
|
4
|
+
|
|
5
|
+
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
|
6
|
+
require "rails/test_help"
|
|
7
|
+
|
|
8
|
+
# dependencies that dummy app depends on
|
|
9
|
+
require "bootstrap_form"
|
|
10
|
+
|
|
11
|
+
Rails.backtrace_cleaner.remove_silencers!
|
|
12
|
+
|
|
13
|
+
# Load support files
|
|
14
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
15
|
+
|
|
16
|
+
# Load fixtures from the engine
|
|
17
|
+
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
|
18
|
+
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
|
19
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
require 'osc/machete'
|
|
3
|
+
|
|
4
|
+
class StatusableTest < Minitest::Unit::TestCase
|
|
5
|
+
# FIXME: the problem here: we are extending, not including, so
|
|
6
|
+
# Statusable#included never called
|
|
7
|
+
#
|
|
8
|
+
# Change the tests to do this appropriately!
|
|
9
|
+
# Or just use a dummy object SimulationJob
|
|
10
|
+
def setup
|
|
11
|
+
@job = SimulationJob.create(pbsid: "123456.oak-batch.osc.edu", job_path: "/path/to/tmp", script_name: "test.sh")
|
|
12
|
+
@job_without_script_name = SimulationJob.create(pbsid: "123456.oak-batch.osc.edu", job_path: "/path/to/tmp")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def teardown
|
|
16
|
+
@job.delete
|
|
17
|
+
@job_without_script_name.delete
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# verify both of these calls work without crashing
|
|
21
|
+
def test_job_getter_works
|
|
22
|
+
assert_equal "test.sh", @job.job.script_name
|
|
23
|
+
assert_nil @job_without_script_name.job.script_name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# if calling status returns :Q for Queued, make sure this
|
|
27
|
+
def test_status_sym
|
|
28
|
+
@job.status = nil
|
|
29
|
+
assert ! @job.submitted?
|
|
30
|
+
assert @job.not_submitted?
|
|
31
|
+
|
|
32
|
+
@job.status = :Q
|
|
33
|
+
|
|
34
|
+
assert @job.submitted?
|
|
35
|
+
assert ! @job.completed?
|
|
36
|
+
assert @job.active?
|
|
37
|
+
assert_equal "Queued", @job.status.to_s
|
|
38
|
+
|
|
39
|
+
@job.status = :R
|
|
40
|
+
assert @job.active?
|
|
41
|
+
assert_equal "Running", @job.status.to_s
|
|
42
|
+
|
|
43
|
+
@job.status = :C
|
|
44
|
+
assert @job.completed?, "completed? should return true when status is C"
|
|
45
|
+
assert ! @job.failed?, "failed? should return false when status is not F"
|
|
46
|
+
|
|
47
|
+
@job.status = :F
|
|
48
|
+
assert @job.completed?, "completed? should return true when status is F"
|
|
49
|
+
assert ! @job.passed?, "passed? should return false when status is F"
|
|
50
|
+
assert @job.failed?, "failed? should return true when status is F"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_status_str
|
|
54
|
+
@job.status = "Q"
|
|
55
|
+
|
|
56
|
+
assert @job.submitted?
|
|
57
|
+
assert ! @job.completed?
|
|
58
|
+
assert @job.active?
|
|
59
|
+
assert_equal "Queued", @job.status.to_s
|
|
60
|
+
|
|
61
|
+
@job.status = "R"
|
|
62
|
+
assert @job.active?
|
|
63
|
+
assert_equal "Running", @job.status.to_s
|
|
64
|
+
|
|
65
|
+
@job.status = "C"
|
|
66
|
+
assert @job.completed?, "completed? should return true when status is C"
|
|
67
|
+
assert ! @job.failed?, "failed? should return false when status is not F"
|
|
68
|
+
|
|
69
|
+
@job.status = "F"
|
|
70
|
+
assert @job.completed?, "completed? should return true when status is F"
|
|
71
|
+
assert ! @job.passed?, "passed? should return false when status is F"
|
|
72
|
+
assert @job.failed?, "failed? should return true when status is F"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_results_valid_hook_called
|
|
77
|
+
OSC::Machete::Job.any_instance.stubs(:status).returns(OSC::Machete::Status.passed)
|
|
78
|
+
@job.status = "R"
|
|
79
|
+
@job.expects(:"results_valid?").at_least_once
|
|
80
|
+
@job.update_status!
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# sometimes, qstat returns "C": still call the hook!
|
|
84
|
+
assert_equal OSC::Machete::Status.passed, @job.job.status
|
|
85
|
+
|
|
86
|
+
@job.status = "R"
|
|
87
|
+
@job.expects(:"results_valid?").at_least_once
|
|
88
|
+
@job.update_status!
|
|
89
|
+
|
|
90
|
+
# but if the status is completed we don't want the hook to run again
|
|
91
|
+
@job.expects(:"results_valid?").never
|
|
92
|
+
@job.status = "C"
|
|
93
|
+
@job.update_status!
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# if status is R but also saved record is also R we shouldn't save
|
|
97
|
+
def test_save_after_update_when_status_returns_symbol
|
|
98
|
+
OSC::Machete::Job.any_instance.stubs(:status).returns(OSC::Machete::Status.running)
|
|
99
|
+
assert OSC::Machete::Status.running, @job.job.status
|
|
100
|
+
|
|
101
|
+
@job.expects(:"save").never
|
|
102
|
+
@job.status = "R"
|
|
103
|
+
@job.update_status!
|
|
104
|
+
|
|
105
|
+
@job.expects(:"save").at_least_once
|
|
106
|
+
@job.status = "Q"
|
|
107
|
+
@job.update_status!
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_update_status_with_not_submitted_with_pbsid
|
|
111
|
+
OSC::Machete::Job.any_instance.stubs(:status).returns(OSC::Machete::Status.running)
|
|
112
|
+
@job.expects(:"save").at_least_once
|
|
113
|
+
@job.status = nil
|
|
114
|
+
@job.update_status!
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_update_status_with_not_submitted_without_pbsid
|
|
118
|
+
OSC::Machete::Job.any_instance.stubs(:status).returns(OSC::Machete::Status.running)
|
|
119
|
+
@job.expects(:"save").never
|
|
120
|
+
@job.pbsid = nil
|
|
121
|
+
@job.status = nil
|
|
122
|
+
@job.update_status!
|
|
123
|
+
end
|
|
124
|
+
end
|