miga-base 0.6.4.2 → 0.7.0.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 +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')
|