miga-base 0.6.4.2 → 0.7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/miga/cli/action/daemon.rb +4 -7
- data/lib/miga/cli/action/lair.rb +25 -15
- data/lib/miga/common/with_daemon.rb +203 -0
- data/lib/miga/common/with_daemon_class.rb +32 -0
- data/lib/miga/daemon.rb +51 -94
- data/lib/miga/daemon/base.rb +0 -18
- data/lib/miga/lair.rb +62 -73
- data/lib/miga/metadata.rb +12 -0
- data/lib/miga/version.rb +2 -2
- data/test/common_test.rb +4 -4
- data/test/daemon_test.rb +64 -51
- data/test/dataset_test.rb +25 -25
- data/test/hook_test.rb +4 -4
- data/test/json_test.rb +2 -2
- data/test/lair_test.rb +93 -0
- data/test/metadata_test.rb +4 -4
- data/test/project_test.rb +12 -14
- data/test/remote_dataset_test.rb +6 -6
- data/test/result_stats_test.rb +2 -2
- data/test/tax_dist_test.rb +5 -5
- data/test/tax_index_test.rb +5 -5
- data/test/taxonomy_test.rb +3 -3
- data/test/with_daemon_test.rb +158 -0
- metadata +7 -3
data/lib/miga/daemon/base.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
|
2
|
-
require 'daemons'
|
3
|
-
require 'date'
|
4
2
|
require 'shellwords'
|
5
3
|
|
6
4
|
class MiGA::Daemon < MiGA::MiGA
|
@@ -55,21 +53,5 @@ module MiGA::Daemon::Base
|
|
55
53
|
# complete
|
56
54
|
def shutdown_when_done?() !!runopts(:shutdown_when_done); end
|
57
55
|
|
58
|
-
##
|
59
|
-
# Initializes the daemon with +opts+
|
60
|
-
def start(opts = []) daemon('start', opts); end
|
61
|
-
|
62
|
-
##
|
63
|
-
# Stops the daemon with +opts+
|
64
|
-
def stop(opts = []) daemon('stop', opts); end
|
65
|
-
|
66
|
-
##
|
67
|
-
# Restarts the daemon with +opts+
|
68
|
-
def restart(opts = []) daemon('restart', opts); end
|
69
|
-
|
70
|
-
##
|
71
|
-
# Returns the status of the daemon with +opts+.
|
72
|
-
def status(opts = []) daemon('status', opts); end
|
73
|
-
|
74
56
|
end
|
75
57
|
|
data/lib/miga/lair.rb
CHANGED
@@ -1,20 +1,14 @@
|
|
1
1
|
# @package MiGA
|
2
2
|
# @license Artistic-2.0
|
3
3
|
|
4
|
-
require 'daemons'
|
5
4
|
require 'miga/daemon'
|
5
|
+
require 'miga/common/with_daemon'
|
6
6
|
|
7
7
|
##
|
8
8
|
# Lair of MiGA Daemons handling job submissions
|
9
9
|
class MiGA::Lair < MiGA::MiGA
|
10
|
-
|
11
|
-
|
12
|
-
# Returns Time
|
13
|
-
def self.last_alive(path)
|
14
|
-
f = File.expand_path('.lair-alive', path)
|
15
|
-
return nil unless File.exist? f
|
16
|
-
Time.parse(File.read(f))
|
17
|
-
end
|
10
|
+
include MiGA::Common::WithDaemon
|
11
|
+
extend MiGA::Common::WithDaemonClass
|
18
12
|
|
19
13
|
# Absolute path to the directory where the projects are located
|
20
14
|
attr_reader :path
|
@@ -22,69 +16,81 @@ class MiGA::Lair < MiGA::MiGA
|
|
22
16
|
# Options used to setup the chief daemon
|
23
17
|
attr_accessor :options
|
24
18
|
|
25
|
-
# Integer indicating the current iteration
|
26
|
-
attr_reader :loop_i
|
27
|
-
|
28
19
|
##
|
29
20
|
# Initialize an inactive daemon for the directory at +path+. See #daemon
|
30
21
|
# to wake the chief daemon. Supported options include:
|
31
22
|
# - json: json definition for all children daemons, by default: nil
|
32
23
|
# - latency: time to wait between iterations in seconds, by default: 120
|
33
24
|
# - wait_for: time to wait for a daemon to report being alive in seconds,
|
34
|
-
# by default:
|
25
|
+
# by default: 30
|
35
26
|
# - keep_inactive: boolean indicating if daemons should stay alive even when
|
36
27
|
# inactive (when all tasks are complete), by default: false
|
37
28
|
# - name: A name for the chief daemon process, by default: basename of +path+
|
29
|
+
# - trust_timestamp: boolean indicating if the +modified+ timestamp of the
|
30
|
+
# project is to be trusted to determine changes in the project,
|
31
|
+
# by default: true
|
32
|
+
# - dry: Only report when daemons would be launched, but don't actually launch
|
33
|
+
# them
|
38
34
|
def initialize(path, opts = {})
|
39
35
|
@path = File.expand_path(path)
|
40
36
|
@options = opts
|
41
|
-
@loop_i = -1
|
42
37
|
{
|
43
38
|
json: nil,
|
44
|
-
latency:
|
45
|
-
wait_for:
|
39
|
+
latency: 30,
|
40
|
+
wait_for: 30,
|
46
41
|
keep_inactive: false,
|
47
|
-
|
42
|
+
trust_timestamp: true,
|
43
|
+
name: File.basename(@path),
|
44
|
+
dry: false
|
48
45
|
}.each { |k, v| @options[k] = v if @options[k].nil? }
|
49
46
|
end
|
50
47
|
|
51
48
|
##
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
# Path to the lair's chief daemon's home
|
50
|
+
alias daemon_home path
|
51
|
+
|
52
|
+
##
|
53
|
+
# Name of the lair's chief daemon
|
54
|
+
def daemon_name
|
55
|
+
"MiGA:#{options[:name]}"
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# First loop of the lair's chief daemon
|
60
|
+
def daemon_first_loop
|
61
|
+
say '-----------------------------------'
|
62
|
+
say '%s launched' % daemon_name
|
63
|
+
say '-----------------------------------'
|
64
|
+
say 'Configuration options:'
|
65
|
+
say options.to_s
|
56
66
|
end
|
57
67
|
|
58
68
|
##
|
59
|
-
#
|
60
|
-
def
|
61
|
-
|
69
|
+
# Run one loop step. Returns a Boolean indicating if the loop should continue.
|
70
|
+
def daemon_loop
|
71
|
+
check_directories
|
72
|
+
return false if options[:dry]
|
73
|
+
sleep(options[:latency])
|
74
|
+
true
|
62
75
|
end
|
63
76
|
|
64
77
|
##
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
MiGA.DEBUG "Lair.daemon #{task} #{opts}"
|
71
|
-
config = default_options
|
72
|
-
opts.unshift(task.to_s)
|
73
|
-
config[:ARGV] = opts
|
74
|
-
# This additional degree of separation below was introduced so the Daemons
|
75
|
-
# package doesn't kill the parent process in workflows.
|
76
|
-
pid = fork do
|
77
|
-
Daemons.run_proc("MiGA:#{options[:name]}", config) { while in_loop; end }
|
78
|
+
# Terminate all daemons in the lair (including the chief daemon)
|
79
|
+
def terminate_daemons
|
80
|
+
terminate_daemon(self)
|
81
|
+
each_project do |project|
|
82
|
+
terminate_daemon(MiGA::Daemon.new(project))
|
78
83
|
end
|
79
|
-
Process.wait(pid) if wait
|
80
|
-
pid
|
81
84
|
end
|
82
85
|
|
83
86
|
##
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
87
|
+
# Send termination message to +daemon+, an object implementing
|
88
|
+
# +MiGA::Common::WithDaemon+
|
89
|
+
def terminate_daemon(daemon)
|
90
|
+
say "Probing #{daemon.class} #{daemon.daemon_home}"
|
91
|
+
if daemon.active?
|
92
|
+
say 'Sending termination message'
|
93
|
+
FileUtils.touch(daemon.terminate_file)
|
88
94
|
end
|
89
95
|
end
|
90
96
|
|
@@ -94,13 +100,14 @@ class MiGA::Lair < MiGA::MiGA
|
|
94
100
|
# Searches for MiGA projects recursively in all
|
95
101
|
# subdirectories that are not MiGA projects.
|
96
102
|
def each_project(dir = path)
|
97
|
-
Dir.
|
103
|
+
Dir.entries(dir).each do |f|
|
104
|
+
next if %w[. ..].include?(f) # Ruby <= 2.3 doesn't have Dir.children
|
98
105
|
f = File.join(dir, f)
|
99
106
|
if MiGA::Project.exist? f
|
100
107
|
project = MiGA::Project.load(f)
|
101
108
|
raise "Cannot load project: #{f}" if project.nil?
|
102
109
|
yield(project)
|
103
|
-
elsif Dir.
|
110
|
+
elsif Dir.exist? f
|
104
111
|
each_project(f) { |project| yield(project) }
|
105
112
|
end
|
106
113
|
end
|
@@ -110,8 +117,13 @@ class MiGA::Lair < MiGA::MiGA
|
|
110
117
|
# Traverse directories checking MiGA projects
|
111
118
|
def check_directories
|
112
119
|
each_project do |project|
|
113
|
-
|
114
|
-
next if
|
120
|
+
d = MiGA::Daemon.new(project)
|
121
|
+
next if d.active?
|
122
|
+
l_alive = d.last_alive
|
123
|
+
unless l_alive.nil?
|
124
|
+
next if options[:trust_timestamp] && project.metadata.updated < l_alive
|
125
|
+
next if l_alive > Time.now - options[:wait_for]
|
126
|
+
end
|
115
127
|
launch_daemon(project)
|
116
128
|
end
|
117
129
|
end
|
@@ -122,32 +134,9 @@ class MiGA::Lair < MiGA::MiGA
|
|
122
134
|
say "Launching daemon: #{project.path}"
|
123
135
|
d = MiGA::Daemon.new(project, options[:json])
|
124
136
|
d.runopts(:shutdown_when_done, true) unless options[:keep_inactive]
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
##
|
129
|
-
# Run one loop step. Returns a Boolean indicating if the loop should continue.
|
130
|
-
def in_loop
|
131
|
-
declare_alive
|
132
|
-
if loop_i == -1
|
133
|
-
say '-----------------------------------'
|
134
|
-
say 'MiGA:%s launched' % options[:name]
|
135
|
-
say '-----------------------------------'
|
136
|
-
say 'Configuration options:'
|
137
|
-
say options.to_s
|
138
|
-
@loop_i = 0
|
137
|
+
unless options[:dry]
|
138
|
+
d.start
|
139
|
+
sleep(1) # <- to make sure the daemon started up (it takes about 0.1 secs)
|
139
140
|
end
|
140
|
-
@loop_i += 1
|
141
|
-
check_directories
|
142
|
-
sleep(options[:latency])
|
143
|
-
true
|
144
|
-
end
|
145
|
-
|
146
|
-
##
|
147
|
-
# Terminates a chief daemon
|
148
|
-
def terminate
|
149
|
-
say 'Terminating chief daemon...'
|
150
|
-
f = File.expand_path('.lair-alive', project.path)
|
151
|
-
File.unlink(f) if File.exist? f
|
152
141
|
end
|
153
142
|
end
|
data/lib/miga/metadata.rb
CHANGED
@@ -135,6 +135,18 @@ class MiGA::Metadata < MiGA::MiGA
|
|
135
135
|
data.each { |k, v| blk.call(k, v) }
|
136
136
|
end
|
137
137
|
|
138
|
+
##
|
139
|
+
# Time of last update
|
140
|
+
def updated
|
141
|
+
Time.parse(self[:updated]) unless self[:updated].nil?
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Time of creation
|
146
|
+
def created
|
147
|
+
Time.parse(self[:created]) unless self[:created].nil?
|
148
|
+
end
|
149
|
+
|
138
150
|
##
|
139
151
|
# Show contents in JSON format as a String
|
140
152
|
def to_json
|
data/lib/miga/version.rb
CHANGED
@@ -10,7 +10,7 @@ module MiGA
|
|
10
10
|
# - Float representing the major.minor version.
|
11
11
|
# - Integer representing gem releases of the current version.
|
12
12
|
# - Integer representing minor changes that require new version number.
|
13
|
-
VERSION = [0.
|
13
|
+
VERSION = [0.7, 0, 0]
|
14
14
|
|
15
15
|
##
|
16
16
|
# Nickname for the current major.minor version.
|
@@ -18,7 +18,7 @@ module MiGA
|
|
18
18
|
|
19
19
|
##
|
20
20
|
# Date of the current gem release.
|
21
|
-
VERSION_DATE = Date.new(2020, 4,
|
21
|
+
VERSION_DATE = Date.new(2020, 4, 18)
|
22
22
|
|
23
23
|
##
|
24
24
|
# Reference of MiGA.
|
data/test/common_test.rb
CHANGED
@@ -33,7 +33,7 @@ class CommonTest < Test::Unit::TestCase
|
|
33
33
|
err = capture_stderr do
|
34
34
|
MiGA::MiGA.DEBUG 'Dandadi'
|
35
35
|
end
|
36
|
-
|
36
|
+
assert_match(/Dandadi\n .*block in test_debug_trace/, err.string)
|
37
37
|
MiGA::MiGA.DEBUG_TRACE_OFF
|
38
38
|
err = capture_stderr do
|
39
39
|
MiGA::MiGA.DEBUG 'Dandada'
|
@@ -66,7 +66,7 @@ class CommonTest < Test::Unit::TestCase
|
|
66
66
|
assert_raise do
|
67
67
|
File.generic_transfer(hello, world, :monkey)
|
68
68
|
end
|
69
|
-
|
69
|
+
assert_path_not_exist(world, 'A monkey shouldn\'t create files.')
|
70
70
|
ensure
|
71
71
|
FileUtils.rm_rf $tmp
|
72
72
|
end
|
@@ -75,8 +75,8 @@ class CommonTest < Test::Unit::TestCase
|
|
75
75
|
assert_equal('Xa sp. C', 'Xa_sp__C'.unmiga_name)
|
76
76
|
assert_equal('X_______', 'X^*.!{}!'.miga_name)
|
77
77
|
assert_equal('aB09', 'aB09'.miga_name)
|
78
|
-
|
79
|
-
|
78
|
+
assert_predicate('R2D2', :miga_name?)
|
79
|
+
assert_not_predicate('C3-PO', :miga_name?)
|
80
80
|
assert_equal("123\n1\n", '1231'.wrap_width(3))
|
81
81
|
end
|
82
82
|
|
data/test/daemon_test.rb
CHANGED
@@ -42,8 +42,8 @@ class DaemonTest < Test::Unit::TestCase
|
|
42
42
|
def test_check_project
|
43
43
|
d1 = $d1
|
44
44
|
helper_datasets_with_results.first.inactivate!
|
45
|
-
out =
|
46
|
-
|
45
|
+
out = capture_stderr { d1.check_project }
|
46
|
+
assert_match(/Queueing miga-project:p/, out.string)
|
47
47
|
assert_equal(1, d1.jobs_to_run.size)
|
48
48
|
assert_equal(:p, d1.jobs_to_run.first[:job])
|
49
49
|
assert_equal('project1:p:miga-project', d1.get_job(:p)[:task_name])
|
@@ -53,10 +53,10 @@ class DaemonTest < Test::Unit::TestCase
|
|
53
53
|
p = $p1
|
54
54
|
d = $d1
|
55
55
|
d.runopts(:maxjobs, 0, true)
|
56
|
-
|
56
|
+
assert_empty(d.jobs_to_run)
|
57
57
|
ds = p.add_dataset('ds1')
|
58
58
|
d.check_datasets
|
59
|
-
|
59
|
+
assert_empty(d.jobs_to_run)
|
60
60
|
FileUtils.cp(
|
61
61
|
File.expand_path('daemon/daemon.json', p.path),
|
62
62
|
File.expand_path('data/01.raw_reads/ds1.1.fastq', p.path)
|
@@ -66,10 +66,10 @@ class DaemonTest < Test::Unit::TestCase
|
|
66
66
|
File.expand_path('data/01.raw_reads/ds1.done', p.path)
|
67
67
|
)
|
68
68
|
ds.first_preprocessing(true)
|
69
|
-
out =
|
69
|
+
out = capture_stderr do
|
70
70
|
d.check_datasets
|
71
71
|
end
|
72
|
-
|
72
|
+
assert_match(/Queueing #{ds.name}:d/, out.string)
|
73
73
|
assert_equal(1, d.jobs_to_run.size)
|
74
74
|
assert_equal('echo project1:d:ds1 >/dev/null', d.jobs_to_run.first[:cmd])
|
75
75
|
assert_equal(d.jobs_to_run.first, d.get_job(:d, ds))
|
@@ -79,15 +79,15 @@ class DaemonTest < Test::Unit::TestCase
|
|
79
79
|
p = $p1
|
80
80
|
d = $d1
|
81
81
|
d.runopts(:latency, 0, true)
|
82
|
-
|
82
|
+
assert_nil(d.loop_i)
|
83
83
|
assert_nil(d.last_alive)
|
84
|
-
out =
|
84
|
+
out = capture_stderr { d.in_loop }.string
|
85
85
|
assert_equal(Time, d.last_alive.class)
|
86
|
-
|
87
|
-
|
86
|
+
assert_match(/-{20}\n.*MiGA:#{p.name} launched/, out)
|
87
|
+
11.times { d.in_loop }
|
88
88
|
assert_equal(11, d.loop_i)
|
89
|
-
out =
|
90
|
-
|
89
|
+
out = capture_stderr { d.in_loop }.string
|
90
|
+
assert_match(/Probing running jobs/, out)
|
91
91
|
assert_equal(0, d.loop_i)
|
92
92
|
end
|
93
93
|
|
@@ -98,25 +98,24 @@ class DaemonTest < Test::Unit::TestCase
|
|
98
98
|
assert_equal(0, d.latency)
|
99
99
|
omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
|
100
100
|
child = $child = d.daemon(:start, ['--shush'])
|
101
|
-
|
102
|
-
|
101
|
+
assert_not_nil(child)
|
102
|
+
assert_gt(child, 1)
|
103
103
|
assert_equal(0, `ps -p "#{child}" -o ppid=`.strip.to_i,
|
104
104
|
'The daemon process should be detached')
|
105
105
|
sleep(3)
|
106
|
-
|
107
|
-
|
108
|
-
out = capture_stdout { d.stop }
|
106
|
+
assert_path_exist(d.pid_file)
|
107
|
+
out = capture_stderr { d.stop }.string
|
109
108
|
assert_raise(Errno::ESRCH) { Process.kill(0, child) }
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
File.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
109
|
+
assert_match(/Sending termination message/, out)
|
110
|
+
assert_path_not_exist(d.pid_file)
|
111
|
+
assert_path_exist(d.output_file)
|
112
|
+
l = File.readlines(d.output_file)
|
113
|
+
{
|
114
|
+
0 => /-{20}\n/,
|
115
|
+
1 => /MiGA:#{p.name} launched/,
|
116
|
+
2 => /-{20}\n/,
|
117
|
+
5 => /Probing running jobs\n/
|
118
|
+
}.each { |k, v| assert_match(v, l[k], "unexpected line: #{k}") }
|
120
119
|
ensure
|
121
120
|
begin
|
122
121
|
Process.kill('KILL', $child) if !$child.nil?
|
@@ -129,8 +128,9 @@ class DaemonTest < Test::Unit::TestCase
|
|
129
128
|
p = MiGA::Project.new(File.expand_path('last_alive', $tmp))
|
130
129
|
d = MiGA::Daemon.new(p)
|
131
130
|
assert_nil(d.last_alive)
|
131
|
+
omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
|
132
132
|
d.declare_alive
|
133
|
-
|
133
|
+
assert_lt(d.last_alive, Time.now)
|
134
134
|
end
|
135
135
|
|
136
136
|
def test_options
|
@@ -150,17 +150,28 @@ class DaemonTest < Test::Unit::TestCase
|
|
150
150
|
end
|
151
151
|
|
152
152
|
def test_say
|
153
|
-
out =
|
154
|
-
|
153
|
+
out = capture_stderr { $d1.say 'Olm' }.string
|
154
|
+
assert_match(/^\[.*\] Olm/, out)
|
155
155
|
end
|
156
156
|
|
157
157
|
def test_terminate
|
158
158
|
d = $d1
|
159
|
+
assert_not_predicate(d, :active?)
|
160
|
+
assert_path_not_exist(d.alive_file)
|
161
|
+
assert_path_not_exist(d.terminated_file)
|
162
|
+
|
163
|
+
omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
|
159
164
|
d.declare_alive
|
165
|
+
assert_predicate(d, :active?)
|
166
|
+
assert_not_nil(d.last_alive)
|
167
|
+
assert_path_exist(d.alive_file)
|
168
|
+
assert_path_not_exist(d.terminated_file)
|
169
|
+
|
170
|
+
d.terminate
|
171
|
+
assert_path_not_exist(d.alive_file)
|
172
|
+
assert_path_exist(d.terminated_file)
|
173
|
+
assert_not_predicate(d, :active?)
|
160
174
|
assert_not_nil(d.last_alive)
|
161
|
-
out = capture_stdout { d.terminate }
|
162
|
-
assert(out.string =~ /Terminating daemon/)
|
163
|
-
assert_nil(d.last_alive)
|
164
175
|
end
|
165
176
|
|
166
177
|
def test_maxjobs_json
|
@@ -168,7 +179,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
168
179
|
helper_datasets_with_results(3)
|
169
180
|
assert_equal(0, d1.jobs_running.size)
|
170
181
|
assert_equal(0, d1.jobs_to_run.size)
|
171
|
-
|
182
|
+
capture_stderr { d1.in_loop }
|
172
183
|
assert_equal(1, d1.jobs_running.size)
|
173
184
|
assert_equal(2, d1.jobs_to_run.size)
|
174
185
|
end
|
@@ -179,7 +190,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
179
190
|
d1.runopts(:maxjobs, 2)
|
180
191
|
assert_equal(0, d1.jobs_running.size)
|
181
192
|
assert_equal(0, d1.jobs_to_run.size)
|
182
|
-
|
193
|
+
capture_stderr { d1.in_loop }
|
183
194
|
assert_equal(2, d1.jobs_running.size)
|
184
195
|
assert_equal(1, d1.jobs_to_run.size)
|
185
196
|
end
|
@@ -195,9 +206,9 @@ class DaemonTest < Test::Unit::TestCase
|
|
195
206
|
File.open(f, 'w') do |h|
|
196
207
|
h.puts '{"jobs_running":[{"ds":1,"ds_name":"d1"},{}],"jobs_to_run":[]}'
|
197
208
|
end
|
198
|
-
out =
|
209
|
+
out = capture_stderr { d1.load_status }.string
|
199
210
|
assert_equal(2, d1.jobs_running.size)
|
200
|
-
|
211
|
+
assert_match(/Loading previous status/, out)
|
201
212
|
assert_equal(MiGA::Dataset, d1.jobs_running[0][:ds].class)
|
202
213
|
assert_nil(d1.jobs_running[1][:ds])
|
203
214
|
end
|
@@ -215,10 +226,10 @@ class DaemonTest < Test::Unit::TestCase
|
|
215
226
|
'{"job":"trimmed_reads","ds":1,"ds_name":"d0"}]' \
|
216
227
|
',"jobs_to_run":[]}'
|
217
228
|
end
|
218
|
-
|
229
|
+
capture_stderr { d1.load_status }
|
219
230
|
assert_equal(3, d1.jobs_running.size)
|
220
|
-
out =
|
221
|
-
|
231
|
+
out = capture_stderr { d1.flush! }.string
|
232
|
+
assert_match(/Completed pid:/, out)
|
222
233
|
assert_equal([], d1.jobs_running)
|
223
234
|
end
|
224
235
|
|
@@ -227,8 +238,8 @@ class DaemonTest < Test::Unit::TestCase
|
|
227
238
|
f = File.join($tmp, 'nodes.txt')
|
228
239
|
File.open(f, 'w') { |h| h.puts 'localhost' }
|
229
240
|
assert_equal(true, d1.next_host)
|
230
|
-
out =
|
231
|
-
|
241
|
+
out = capture_stderr { d1.runopts(:nodelist, f) }.string
|
242
|
+
assert_match(/Reading node list:/, out)
|
232
243
|
assert_equal(true, d1.next_host)
|
233
244
|
d1.runopts(:type, 'ssh')
|
234
245
|
assert_equal(0, d1.next_host)
|
@@ -236,14 +247,14 @@ class DaemonTest < Test::Unit::TestCase
|
|
236
247
|
File.open(f, 'w') do |h|
|
237
248
|
h.puts '{"jobs_running":[{"job":"p","hostk":0}], "jobs_to_run":[]}'
|
238
249
|
end
|
239
|
-
|
250
|
+
capture_stderr { d1.load_status }
|
240
251
|
assert_nil(d1.next_host)
|
241
252
|
end
|
242
253
|
|
243
254
|
def test_shutdown_when_done
|
244
255
|
$d1.runopts(:shutdown_when_done, true)
|
245
|
-
out =
|
246
|
-
|
256
|
+
out = capture_stderr { assert { !$d1.in_loop } }.string
|
257
|
+
assert_match(/Nothing else to do/, out)
|
247
258
|
end
|
248
259
|
|
249
260
|
def test_update_format_0
|
@@ -276,7 +287,7 @@ class DaemonTest < Test::Unit::TestCase
|
|
276
287
|
d1.runopts(:nodelist, '$MIGA_TEST_NODELIST')
|
277
288
|
end
|
278
289
|
ENV['MIGA_TEST_NODELIST'] = f
|
279
|
-
|
290
|
+
capture_stderr { d1.runopts(:nodelist, '$MIGA_TEST_NODELIST') }
|
280
291
|
helper_daemon_launch_job
|
281
292
|
assert_equal("project1:p:miga-project\n", File.read(t))
|
282
293
|
end
|
@@ -293,20 +304,22 @@ class DaemonTest < Test::Unit::TestCase
|
|
293
304
|
d1.runopts(:type, 'qsub')
|
294
305
|
d1.runopts(:cmd, 'echo ""')
|
295
306
|
helper_datasets_with_results.first.inactivate!
|
296
|
-
|
297
|
-
|
298
|
-
|
307
|
+
capture_stderr { d1.check_project }
|
308
|
+
omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
|
309
|
+
out = capture_stderr { d1.launch_job(d1.jobs_to_run.shift) }.string
|
310
|
+
assert_match(/Unsuccessful project1:p:miga-project, rescheduling/, out)
|
299
311
|
assert_equal(0, d1.jobs_running.size)
|
300
312
|
assert_equal(1, d1.jobs_to_run.size)
|
301
313
|
end
|
302
314
|
|
303
315
|
def helper_daemon_launch_job
|
316
|
+
omit_if($jruby_tests, 'JRuby doesn\'t implement fork.')
|
304
317
|
d1 = $d1
|
305
318
|
helper_datasets_with_results.first.inactivate!
|
306
319
|
assert_equal(0, d1.jobs_to_run.size, 'The queue should be empty')
|
307
|
-
|
320
|
+
capture_stderr { d1.check_project }
|
308
321
|
assert_equal(1, d1.jobs_to_run.size, 'The queue should have one job')
|
309
|
-
|
322
|
+
capture_stderr { d1.flush! }
|
310
323
|
sleep(1)
|
311
324
|
assert_equal(0, d1.jobs_to_run.size, 'There should be nothing running')
|
312
325
|
assert_equal(1, d1.jobs_running.size, 'There should be one job running')
|