bluepill 0.0.68 → 0.0.69
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/README.md +1 -2
- data/bin/bluepill +19 -20
- data/bin/sample_forking_server +26 -13
- data/bluepill.gemspec +12 -18
- data/lib/bluepill.rb +12 -12
- data/lib/bluepill/application.rb +64 -71
- data/lib/bluepill/application/client.rb +0 -2
- data/lib/bluepill/application/server.rb +1 -3
- data/lib/bluepill/condition_watch.rb +12 -7
- data/lib/bluepill/controller.rb +37 -42
- data/lib/bluepill/dsl.rb +1 -2
- data/lib/bluepill/dsl/app_proxy.rb +3 -4
- data/lib/bluepill/dsl/process_factory.rb +40 -44
- data/lib/bluepill/dsl/process_proxy.rb +4 -5
- data/lib/bluepill/group.rb +15 -21
- data/lib/bluepill/logger.rb +4 -4
- data/lib/bluepill/process.rb +107 -109
- data/lib/bluepill/process_conditions.rb +1 -3
- data/lib/bluepill/process_conditions/always_true.rb +2 -3
- data/lib/bluepill/process_conditions/cpu_usage.rb +0 -1
- data/lib/bluepill/process_conditions/file_time.rb +5 -6
- data/lib/bluepill/process_conditions/http.rb +11 -9
- data/lib/bluepill/process_conditions/mem_usage.rb +6 -7
- data/lib/bluepill/process_conditions/process_condition.rb +4 -5
- data/lib/bluepill/process_conditions/running_time.rb +1 -2
- data/lib/bluepill/process_conditions/zombie_process.rb +1 -2
- data/lib/bluepill/process_journal.rb +18 -21
- data/lib/bluepill/process_statistics.rb +2 -4
- data/lib/bluepill/socket.rb +13 -16
- data/lib/bluepill/system.rb +57 -63
- data/lib/bluepill/trigger.rb +9 -11
- data/lib/bluepill/triggers/flapping.rb +12 -16
- data/lib/bluepill/util/rotational_array.rb +1 -2
- data/lib/bluepill/version.rb +1 -2
- metadata +4 -28
- data/.gitignore +0 -12
- data/.rspec +0 -1
- data/.travis.yml +0 -17
- data/Gemfile +0 -27
- data/Rakefile +0 -38
- data/examples/example.rb +0 -87
- data/examples/new_example.rb +0 -89
- data/examples/new_runit_example.rb +0 -29
- data/examples/runit_example.rb +0 -26
- data/local-bluepill +0 -130
- data/spec/lib/bluepill/application_spec.rb +0 -51
- data/spec/lib/bluepill/logger_spec.rb +0 -3
- data/spec/lib/bluepill/process_spec.rb +0 -135
- data/spec/lib/bluepill/process_statistics_spec.rb +0 -24
- data/spec/lib/bluepill/system_spec.rb +0 -45
- data/spec/spec_helper.rb +0 -26
@@ -1,29 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'bluepill'
|
4
|
-
require 'logger'
|
5
|
-
|
6
|
-
# ATTENTION:
|
7
|
-
# You must declare only one application per config when foreground mode specified
|
8
|
-
#
|
9
|
-
# http://github.com/Undev/runit-man used as example of monitored application.
|
10
|
-
|
11
|
-
# Note that this syntax supported from bluepill 0.0.50
|
12
|
-
|
13
|
-
Bluepill.application(:runit_man, :foreground => true) do
|
14
|
-
process("runit-man") do
|
15
|
-
pid_file "/etc/service/runit-man/supervise/pid"
|
16
|
-
|
17
|
-
start_command "/usr/bin/sv start runit-man"
|
18
|
-
stop_command "/usr/bin/sv stop runit-man"
|
19
|
-
restart_command "/usr/bin/sv restart runit-man"
|
20
|
-
|
21
|
-
start_grace_time 1.seconds
|
22
|
-
restart_grace_time 7.seconds
|
23
|
-
stop_grace_time 7.seconds
|
24
|
-
|
25
|
-
checks :http, :within => 30.seconds, :retry_in => 7.seconds, :every => 30.seconds,
|
26
|
-
:url => 'http://localhost:4567/', :kind => :success, :pattern => /html/, :timeout => 3.seconds
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
data/examples/runit_example.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'bluepill'
|
4
|
-
require 'logger'
|
5
|
-
|
6
|
-
# ATTENTION:
|
7
|
-
# You must declare only one application per config when foreground mode specified
|
8
|
-
#
|
9
|
-
# http://github.com/Undev/runit-man used as example of monitored application.
|
10
|
-
|
11
|
-
Bluepill.application(:runit_man, :foreground => true) do |app|
|
12
|
-
app.process("runit-man") do |process|
|
13
|
-
process.pid_file = "/etc/service/runit-man/supervise/pid"
|
14
|
-
|
15
|
-
process.start_command = "/usr/bin/sv start runit-man"
|
16
|
-
process.stop_command = "/usr/bin/sv stop runit-man"
|
17
|
-
process.restart_command = "/usr/bin/sv restart runit-man"
|
18
|
-
|
19
|
-
process.start_grace_time = 1.seconds
|
20
|
-
process.restart_grace_time = 7.seconds
|
21
|
-
process.stop_grace_time = 7.seconds
|
22
|
-
|
23
|
-
process.checks :http, :within => 30.seconds, :retry_in => 7.seconds, :every => 30.seconds,
|
24
|
-
:url => 'http://localhost:4567/', :kind => :success, :pattern => /html/, :timeout => 3.seconds
|
25
|
-
end
|
26
|
-
end
|
data/local-bluepill
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler/setup'
|
5
|
-
$LOAD_PATH.unshift(File.expand_path('lib', File.dirname(__FILE__)))
|
6
|
-
|
7
|
-
require 'optparse'
|
8
|
-
require 'bluepill'
|
9
|
-
|
10
|
-
begin
|
11
|
-
require 'rbconfig'
|
12
|
-
rescue LoadError
|
13
|
-
end
|
14
|
-
|
15
|
-
RbConfig = Config unless Object.const_defined?(:RbConfig)
|
16
|
-
|
17
|
-
# Default options
|
18
|
-
options = {
|
19
|
-
:log_file => "/var/log/bluepill.log",
|
20
|
-
:base_dir => ENV['BLUEPILL_BASE_DIR'] || (::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : "/var/run/bluepill"),
|
21
|
-
:privileged => true,
|
22
|
-
:timeout => 10,
|
23
|
-
:attempts => 1
|
24
|
-
}
|
25
|
-
|
26
|
-
OptionParser.new do |opts|
|
27
|
-
opts.banner = "Usage: bluepill [app] cmd [options]"
|
28
|
-
opts.on('-l', "--logfile LOGFILE", "Path to logfile, defaults to #{options[:log_file]}") do |file|
|
29
|
-
options[:log_file] = file
|
30
|
-
end
|
31
|
-
|
32
|
-
opts.on('-c', "--base-dir DIR", "Directory to store bluepill socket and pid files, defaults to #{options[:base_dir]}") do |base_dir|
|
33
|
-
options[:base_dir] = base_dir
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("-v", "--version") do
|
37
|
-
puts "bluepill, version #{Bluepill::VERSION}"
|
38
|
-
exit
|
39
|
-
end
|
40
|
-
|
41
|
-
opts.on("--[no-]privileged", "Allow/disallow to run #{$0} as non-privileged process. disallowed by default") do |v|
|
42
|
-
options[:privileged] = v
|
43
|
-
end
|
44
|
-
|
45
|
-
opts.on('-t', '--timeout Seconds', Integer, "Timeout for commands sent to the daemon, in seconds. Defaults to 10.") do |timeout|
|
46
|
-
options[:timeout] = timeout
|
47
|
-
end
|
48
|
-
|
49
|
-
opts.on('--attempts Count', Integer, "Attempts for commands sent to the daemon, in seconds. Defaults to 1.") do |attempts|
|
50
|
-
options[:attempts] = attempts
|
51
|
-
end
|
52
|
-
|
53
|
-
help = proc do
|
54
|
-
puts opts
|
55
|
-
puts
|
56
|
-
puts "Commands:"
|
57
|
-
puts " load CONFIG_FILE\t\tLoads new instance of bluepill using the specified config file"
|
58
|
-
puts " status\t\t\tLists the status of the proceses for the specified app"
|
59
|
-
puts " start [TARGET]\t\tIssues the start command for the target process or group, defaults to all processes"
|
60
|
-
puts " stop [TARGET]\t\tIssues the stop command for the target process or group, defaults to all processes"
|
61
|
-
puts " restart [TARGET]\t\tIssues the restart command for the target process or group, defaults to all processes"
|
62
|
-
puts " unmonitor [TARGET]\t\tStop monitoring target process or group, defaults to all processes"
|
63
|
-
puts " log [TARGET]\t\tShow the log for the specified process or group, defaults to all for app"
|
64
|
-
puts " quit\t\t\tStop bluepill"
|
65
|
-
puts
|
66
|
-
puts "See http://github.com/bluepill-rb/bluepill#readme"
|
67
|
-
exit
|
68
|
-
end
|
69
|
-
|
70
|
-
opts.on_tail('-h','--help', 'Show this message', &help)
|
71
|
-
help.call if ARGV.empty?
|
72
|
-
end.parse!
|
73
|
-
|
74
|
-
# Check for root
|
75
|
-
if options[:privileged] && ::Process.euid != 0
|
76
|
-
$stderr.puts "You must run bluepill as root or use --no-privileged option."
|
77
|
-
exit(3)
|
78
|
-
end
|
79
|
-
|
80
|
-
APPLICATION_COMMANDS = %w(status start stop restart unmonitor quit log)
|
81
|
-
|
82
|
-
controller = Bluepill::Controller.new(options.slice(:base_dir, :log_file))
|
83
|
-
|
84
|
-
if controller.running_applications.include?(File.basename($0)) && File.symlink?($0)
|
85
|
-
# bluepill was called as a symlink with the name of the target application
|
86
|
-
options[:application] = File.basename($0)
|
87
|
-
elsif controller.running_applications.include?(ARGV.first)
|
88
|
-
# the first arg is the application name
|
89
|
-
options[:application] = ARGV.shift
|
90
|
-
elsif APPLICATION_COMMANDS.include?(ARGV.first)
|
91
|
-
if controller.running_applications.length == 1
|
92
|
-
# there is only one, let's just use that
|
93
|
-
options[:application] = controller.running_applications.first
|
94
|
-
elsif controller.running_applications.length > 1
|
95
|
-
# There is more than one, tell them the list and exit
|
96
|
-
$stderr.puts "You must specify an application name to run that command. Here's the list of running applications:"
|
97
|
-
controller.running_applications.each_with_index do |app, index|
|
98
|
-
$stderr.puts " #{index + 1}. #{app}"
|
99
|
-
end
|
100
|
-
$stderr.puts "Usage: bluepill [app] cmd [options]"
|
101
|
-
exit(1)
|
102
|
-
else
|
103
|
-
# There are none running AND they aren't trying to start one
|
104
|
-
$stderr.puts "Error: There are no running bluepill daemons.\nTo start a bluepill daemon, use: bluepill load <config file>"
|
105
|
-
exit(2)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
options[:command] = ARGV.shift
|
110
|
-
|
111
|
-
if options[:command] == "load"
|
112
|
-
file = ARGV.shift
|
113
|
-
if File.exists?(file)
|
114
|
-
# Restart the ruby interpreter for the config file so that anything loaded here
|
115
|
-
# does not stay in memory for the daemon
|
116
|
-
ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
117
|
-
load_path = File.expand_path("#{File.dirname(__FILE__)}/lib")
|
118
|
-
file_path = File.expand_path(file)
|
119
|
-
ENV['BLUEPILL_BASE_DIR'] = options[:base_dir]
|
120
|
-
|
121
|
-
exec(ruby, "-I#{load_path}", '-rbluepill', file_path)
|
122
|
-
|
123
|
-
else
|
124
|
-
$stderr.puts "Can't find file: #{file}"
|
125
|
-
end
|
126
|
-
else
|
127
|
-
target = ARGV.shift
|
128
|
-
controller.handle_command(options[:application], options[:command], target)
|
129
|
-
end
|
130
|
-
|
@@ -1,51 +0,0 @@
|
|
1
|
-
describe Bluepill::Application do
|
2
|
-
describe "#initialize" do
|
3
|
-
let(:options){ {} }
|
4
|
-
subject {described_class.new('test', options)}
|
5
|
-
before(:each) {expect_any_instance_of(described_class).to receive(:setup_pids_dir)}
|
6
|
-
|
7
|
-
context "when euid is not root" do
|
8
|
-
before(:each) {allow(::Process).to receive(:euid).and_return(1)}
|
9
|
-
|
10
|
-
describe '#base_dir' do
|
11
|
-
subject { super().base_dir }
|
12
|
-
it{ should eq(File.join(ENV['HOME'], '.bluepill')) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
context "when euid is root" do
|
16
|
-
before(:each) {allow(::Process).to receive(:euid).and_return(0)}
|
17
|
-
|
18
|
-
describe '#base_dir' do
|
19
|
-
subject { super().base_dir }
|
20
|
-
it { should eq('/var/run/bluepill') }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "when option base_dir is specified" do
|
25
|
-
let(:options) { {:base_dir=>'/var/bluepill'} }
|
26
|
-
|
27
|
-
describe '#base_dir' do
|
28
|
-
subject { super().base_dir }
|
29
|
-
it { should eq(options[:base_dir]) }
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context "when environment BLUEPILL_BASE_DIR is specified" do
|
34
|
-
before(:each) {ENV['BLUEPILL_BASE_DIR'] = '/bluepill'}
|
35
|
-
|
36
|
-
describe '#base_dir' do
|
37
|
-
subject { super().base_dir }
|
38
|
-
it { should eq(ENV['BLUEPILL_BASE_DIR']) }
|
39
|
-
end
|
40
|
-
|
41
|
-
context "and option base_dir is specified" do
|
42
|
-
let(:options) { {:base_dir=>'/var/bluepill'} }
|
43
|
-
|
44
|
-
describe '#base_dir' do
|
45
|
-
subject { super().base_dir }
|
46
|
-
it { should eq(options[:base_dir]) }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
describe Bluepill::Process do
|
2
|
-
before(:all) do
|
3
|
-
Bluepill::ProcessJournal.base_dir = './.bluepill'
|
4
|
-
Bluepill::ProcessJournal.logger = Bluepill::Logger.new(:log_file => 'bluepill.log', :stdout => false).prefix_with('rspec')
|
5
|
-
end
|
6
|
-
|
7
|
-
subject do
|
8
|
-
Bluepill::Process.new(:proc_name, [], :logger => Bluepill::Logger.new)
|
9
|
-
end
|
10
|
-
|
11
|
-
describe "#initialize" do
|
12
|
-
context "defaults" do
|
13
|
-
[
|
14
|
-
:start_command, :stop_command, :restart_command, :stdout, :stderr, :stdin,
|
15
|
-
:daemonize, :pid_file, :working_dir, :uid, :gid, :child_process_factory,
|
16
|
-
:pid_command, :auto_start, :supplementary_groups, :stop_signals
|
17
|
-
].each do |attr|
|
18
|
-
describe attr do
|
19
|
-
subject { super().send(attr) }
|
20
|
-
it { should be_nil }
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '#monitor_children' do
|
25
|
-
subject { super().monitor_children }
|
26
|
-
it { should be false }
|
27
|
-
end
|
28
|
-
|
29
|
-
describe '#cache_actual_pid' do
|
30
|
-
subject { super().cache_actual_pid }
|
31
|
-
it { should be true }
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#start_grace_time' do
|
35
|
-
subject { super().start_grace_time }
|
36
|
-
it { should eq 3 }
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '#stop_grace_time' do
|
40
|
-
subject { super().stop_grace_time }
|
41
|
-
it { should eq 3 }
|
42
|
-
end
|
43
|
-
|
44
|
-
describe '#restart_grace_time' do
|
45
|
-
subject { super().restart_grace_time }
|
46
|
-
it { should eq 3 }
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#on_start_timeout' do
|
50
|
-
subject { super().on_start_timeout }
|
51
|
-
it { should eq "start" }
|
52
|
-
end
|
53
|
-
|
54
|
-
describe '#environment' do
|
55
|
-
subject { super().environment }
|
56
|
-
it { should eq Hash[] }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context "overrides" do
|
61
|
-
subject { Bluepill::Process.new(:proc_name, [], :start_grace_time => 17) }
|
62
|
-
|
63
|
-
describe '#start_grace_time' do
|
64
|
-
subject { super().start_grace_time }
|
65
|
-
it { should eq 17 }
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "#start_process" do
|
71
|
-
it "functions" do
|
72
|
-
allow(subject).to receive(:start_command) { "/etc/init.d/script start" }
|
73
|
-
allow(subject).to receive(:on_start_timeout) { "freakout" }
|
74
|
-
allow(subject.logger).to receive(:warning)
|
75
|
-
allow(subject).to receive(:daemonize?) { false }
|
76
|
-
|
77
|
-
expect(subject).to receive(:with_timeout).
|
78
|
-
with(3, "freakout").
|
79
|
-
and_yield
|
80
|
-
|
81
|
-
expect(Bluepill::System).to receive(:execute_blocking).
|
82
|
-
with("/etc/init.d/script start", subject.system_command_options).
|
83
|
-
and_return(:exit_code => 0)
|
84
|
-
|
85
|
-
subject.start_process
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "#stop_process" do
|
89
|
-
it "functions" do
|
90
|
-
allow(subject).to receive(:stop_command) { "/etc/init.d/script stop" }
|
91
|
-
allow(subject.logger).to receive(:warning)
|
92
|
-
expect(subject).to receive(:with_timeout).
|
93
|
-
with(3, "stop").
|
94
|
-
and_yield
|
95
|
-
|
96
|
-
expect(Bluepill::System).to receive(:execute_blocking).
|
97
|
-
with("/etc/init.d/script stop", subject.system_command_options).
|
98
|
-
and_return(:exit_code => 0)
|
99
|
-
|
100
|
-
subject.stop_process
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe "#restart_process" do
|
105
|
-
it "functions" do
|
106
|
-
allow(subject).to receive(:restart_command) { "/etc/init.d/script restart" }
|
107
|
-
allow(subject.logger).to receive(:warning)
|
108
|
-
expect(subject).to receive(:with_timeout).
|
109
|
-
with(3, "restart").
|
110
|
-
and_yield
|
111
|
-
|
112
|
-
expect(Bluepill::System).to receive(:execute_blocking).
|
113
|
-
with("/etc/init.d/script restart", subject.system_command_options).
|
114
|
-
and_return(:exit_code => 0)
|
115
|
-
|
116
|
-
subject.restart_process
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe "#with_timeout" do
|
122
|
-
let(:block) { proc { nil } }
|
123
|
-
|
124
|
-
before(:each) do
|
125
|
-
allow(subject.logger).to receive(:err)
|
126
|
-
expect(Timeout).to receive(:timeout).with(3.to_f, &block).and_raise(Timeout::Error)
|
127
|
-
end
|
128
|
-
|
129
|
-
it "proceeds to next_state on timeout." do
|
130
|
-
expect(subject).to receive(:dispatch!).with("state_override")
|
131
|
-
subject.with_timeout(3, "state_override", &block)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
describe Bluepill::ProcessStatistics do
|
2
|
-
before(:each) do
|
3
|
-
@stats = Bluepill::ProcessStatistics.new
|
4
|
-
end
|
5
|
-
|
6
|
-
it "should record events" do
|
7
|
-
@stats.record_event('some event', 'some reason')
|
8
|
-
@stats.record_event('another event', 'another reason')
|
9
|
-
expect(@stats.events.size).to eq(2)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should record #EVENTS_TO_PERSIST events" do
|
13
|
-
(2 * Bluepill::ProcessStatistics::EVENTS_TO_PERSIST).times do
|
14
|
-
@stats.record_event('some event', 'some reason')
|
15
|
-
end
|
16
|
-
expect(@stats.events.size).to eq(Bluepill::ProcessStatistics::EVENTS_TO_PERSIST)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should return event history" do
|
20
|
-
@stats.record_event('some event', 'some reason')
|
21
|
-
expect(@stats.to_s).to match(/some reason/)
|
22
|
-
expect(@stats.to_s).to match(/event history/)
|
23
|
-
end
|
24
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
describe Bluepill::System do
|
2
|
-
describe :pid_alive? do
|
3
|
-
it "should be true if process responds to zero signal" do
|
4
|
-
expect(Process).to receive(:kill).with(0, 555).and_return(0)
|
5
|
-
expect(Bluepill::System).to be_pid_alive(555)
|
6
|
-
end
|
7
|
-
|
8
|
-
it "should be false if process throws exception on zero signal" do
|
9
|
-
expect(Process).to receive(:kill).with(0, 555).and_raise(Errno::ESRCH)
|
10
|
-
expect(Bluepill::System).not_to be_pid_alive(555)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe :store do
|
15
|
-
it "should be Hash" do
|
16
|
-
expect(Bluepill::System.store).to be_kind_of(Hash)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should return same Hash or every call" do
|
20
|
-
expect(Bluepill::System.store).to be_equal(Bluepill::System.store)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should store assigned pairs" do
|
24
|
-
Bluepill::System.store[:somekey] = 10
|
25
|
-
expect(Bluepill::System.store[:somekey]).to be_eql(10)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe :reset_data do
|
30
|
-
it 'should clear the #store' do
|
31
|
-
Bluepill::System.store[:anotherkey] = Faker::Lorem.sentence
|
32
|
-
Bluepill::System.reset_data
|
33
|
-
expect(Bluepill::System.store).to be_empty
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe :parse_etime do
|
38
|
-
it "should parse etime format" do
|
39
|
-
expect(Bluepill::System.parse_elapsed_time("400-00:04:01")).to be_equal(34560241)
|
40
|
-
expect(Bluepill::System.parse_elapsed_time("02:04:02")).to be_equal(7442)
|
41
|
-
expect(Bluepill::System.parse_elapsed_time("20:03")).to be_equal(1203)
|
42
|
-
expect(Bluepill::System.parse_elapsed_time("invalid")).to be_equal(0)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|