mcproc 2016.2.20
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/Announce.txt +135 -0
- data/Gemfile +9 -0
- data/History.txt +469 -0
- data/LICENSE +22 -0
- data/README.md +37 -0
- data/Rakefile +185 -0
- data/TODO.md +37 -0
- data/bin/mcproc +134 -0
- data/doc/intro.asciidoc +20 -0
- data/doc/mcproc.asciidoc +1592 -0
- data/ext/god/.gitignore +5 -0
- data/ext/god/extconf.rb +56 -0
- data/ext/god/kqueue_handler.c +133 -0
- data/ext/god/netlink_handler.c +182 -0
- data/lib/god.rb +780 -0
- data/lib/god/behavior.rb +52 -0
- data/lib/god/behaviors/clean_pid_file.rb +21 -0
- data/lib/god/behaviors/clean_unix_socket.rb +21 -0
- data/lib/god/behaviors/notify_when_flapping.rb +51 -0
- data/lib/god/cli/command.rb +268 -0
- data/lib/god/cli/run.rb +170 -0
- data/lib/god/cli/version.rb +23 -0
- data/lib/god/compat19.rb +33 -0
- data/lib/god/condition.rb +96 -0
- data/lib/god/conditions/always.rb +36 -0
- data/lib/god/conditions/complex.rb +86 -0
- data/lib/god/conditions/cpu_usage.rb +80 -0
- data/lib/god/conditions/degrading_lambda.rb +52 -0
- data/lib/god/conditions/disk_usage.rb +32 -0
- data/lib/god/conditions/file_mtime.rb +28 -0
- data/lib/god/conditions/file_touched.rb +44 -0
- data/lib/god/conditions/flapping.rb +128 -0
- data/lib/god/conditions/http_response_code.rb +184 -0
- data/lib/god/conditions/lambda.rb +25 -0
- data/lib/god/conditions/memory_usage.rb +82 -0
- data/lib/god/conditions/process_exits.rb +66 -0
- data/lib/god/conditions/process_running.rb +63 -0
- data/lib/god/conditions/socket_responding.rb +142 -0
- data/lib/god/conditions/tries.rb +44 -0
- data/lib/god/configurable.rb +57 -0
- data/lib/god/contact.rb +114 -0
- data/lib/god/contacts/airbrake.rb +44 -0
- data/lib/god/contacts/campfire.rb +121 -0
- data/lib/god/contacts/email.rb +130 -0
- data/lib/god/contacts/hipchat.rb +117 -0
- data/lib/god/contacts/jabber.rb +75 -0
- data/lib/god/contacts/prowl.rb +57 -0
- data/lib/god/contacts/scout.rb +55 -0
- data/lib/god/contacts/sensu.rb +59 -0
- data/lib/god/contacts/slack.rb +98 -0
- data/lib/god/contacts/statsd.rb +46 -0
- data/lib/god/contacts/twitter.rb +51 -0
- data/lib/god/contacts/webhook.rb +74 -0
- data/lib/god/driver.rb +238 -0
- data/lib/god/errors.rb +24 -0
- data/lib/god/event_handler.rb +112 -0
- data/lib/god/event_handlers/dummy_handler.rb +13 -0
- data/lib/god/event_handlers/kqueue_handler.rb +17 -0
- data/lib/god/event_handlers/netlink_handler.rb +13 -0
- data/lib/god/logger.rb +109 -0
- data/lib/god/metric.rb +87 -0
- data/lib/god/process.rb +381 -0
- data/lib/god/registry.rb +32 -0
- data/lib/god/simple_logger.rb +59 -0
- data/lib/god/socket.rb +113 -0
- data/lib/god/sugar.rb +62 -0
- data/lib/god/sys_logger.rb +45 -0
- data/lib/god/system/portable_poller.rb +42 -0
- data/lib/god/system/process.rb +50 -0
- data/lib/god/system/slash_proc_poller.rb +92 -0
- data/lib/god/task.rb +552 -0
- data/lib/god/timeline.rb +25 -0
- data/lib/god/trigger.rb +43 -0
- data/lib/god/watch.rb +340 -0
- data/mcproc.gemspec +192 -0
- data/test/configs/child_events/child_events.god +44 -0
- data/test/configs/child_events/simple_server.rb +3 -0
- data/test/configs/child_polls/child_polls.god +37 -0
- data/test/configs/child_polls/simple_server.rb +12 -0
- data/test/configs/complex/complex.god +59 -0
- data/test/configs/complex/simple_server.rb +3 -0
- data/test/configs/contact/contact.god +118 -0
- data/test/configs/contact/simple_server.rb +3 -0
- data/test/configs/daemon_events/daemon_events.god +37 -0
- data/test/configs/daemon_events/simple_server.rb +8 -0
- data/test/configs/daemon_events/simple_server_stop.rb +11 -0
- data/test/configs/daemon_polls/daemon_polls.god +17 -0
- data/test/configs/daemon_polls/simple_server.rb +6 -0
- data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
- data/test/configs/degrading_lambda/tcp_server.rb +15 -0
- data/test/configs/keepalive/keepalive.god +9 -0
- data/test/configs/keepalive/keepalive.rb +12 -0
- data/test/configs/lifecycle/lifecycle.god +25 -0
- data/test/configs/matias/matias.god +50 -0
- data/test/configs/real.rb +59 -0
- data/test/configs/running_load/running_load.god +16 -0
- data/test/configs/stop_options/simple_server.rb +12 -0
- data/test/configs/stop_options/stop_options.god +39 -0
- data/test/configs/stress/simple_server.rb +3 -0
- data/test/configs/stress/stress.god +15 -0
- data/test/configs/task/logs/.placeholder +0 -0
- data/test/configs/task/task.god +26 -0
- data/test/configs/test.rb +61 -0
- data/test/configs/usr1_trapper.rb +10 -0
- data/test/helper.rb +172 -0
- data/test/suite.rb +6 -0
- data/test/test_airbrake.rb +14 -0
- data/test/test_behavior.rb +18 -0
- data/test/test_campfire.rb +22 -0
- data/test/test_condition.rb +52 -0
- data/test/test_conditions_disk_usage.rb +50 -0
- data/test/test_conditions_http_response_code.rb +109 -0
- data/test/test_conditions_process_running.rb +40 -0
- data/test/test_conditions_socket_responding.rb +176 -0
- data/test/test_conditions_tries.rb +67 -0
- data/test/test_contact.rb +109 -0
- data/test/test_driver.rb +26 -0
- data/test/test_email.rb +34 -0
- data/test/test_event_handler.rb +82 -0
- data/test/test_god.rb +710 -0
- data/test/test_god_system.rb +201 -0
- data/test/test_handlers_kqueue_handler.rb +16 -0
- data/test/test_hipchat.rb +23 -0
- data/test/test_jabber.rb +29 -0
- data/test/test_logger.rb +55 -0
- data/test/test_metric.rb +74 -0
- data/test/test_process.rb +263 -0
- data/test/test_prowl.rb +15 -0
- data/test/test_registry.rb +15 -0
- data/test/test_sensu.rb +11 -0
- data/test/test_slack.rb +57 -0
- data/test/test_socket.rb +34 -0
- data/test/test_statsd.rb +22 -0
- data/test/test_sugar.rb +42 -0
- data/test/test_system_portable_poller.rb +17 -0
- data/test/test_system_process.rb +30 -0
- data/test/test_task.rb +246 -0
- data/test/test_timeline.rb +37 -0
- data/test/test_trigger.rb +63 -0
- data/test/test_watch.rb +286 -0
- data/test/test_webhook.rb +22 -0
- metadata +475 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
God::Contacts::Twitter.settings = {
|
2
|
+
# this is for my 'mojombo2' twitter test account
|
3
|
+
# feel free to use it for testing your conditions
|
4
|
+
:username => 'mojombo@gmail.com',
|
5
|
+
:password => 'gok9we3ot1av2e'
|
6
|
+
}
|
7
|
+
|
8
|
+
God.contact(:twitter) do |c|
|
9
|
+
c.name = 'tom2'
|
10
|
+
c.group = 'developers'
|
11
|
+
end
|
12
|
+
|
13
|
+
God.watch do |w|
|
14
|
+
w.name = "lifecycle"
|
15
|
+
w.interval = 5.seconds
|
16
|
+
w.start = "/dev/null"
|
17
|
+
|
18
|
+
# lifecycle
|
19
|
+
w.lifecycle do |on|
|
20
|
+
on.condition(:always) do |c|
|
21
|
+
c.what = true
|
22
|
+
c.notify = "tom2"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
$pid_file = "/tmp/matias.pid"
|
2
|
+
|
3
|
+
God.task do |w|
|
4
|
+
w.name = "watcher"
|
5
|
+
w.interval = 5.seconds
|
6
|
+
w.valid_states = [:init, :up, :down]
|
7
|
+
w.initial_state = :init
|
8
|
+
|
9
|
+
# determine the state on startup
|
10
|
+
w.transition(:init, { true => :up, false => :down }) do |on|
|
11
|
+
on.condition(:process_running) do |c|
|
12
|
+
c.running = true
|
13
|
+
c.pid_file = $pid_file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# when process is up
|
18
|
+
w.transition(:up, :down) do |on|
|
19
|
+
# transition to 'start' if process goes down
|
20
|
+
on.condition(:process_running) do |c|
|
21
|
+
c.running = false
|
22
|
+
c.pid_file = $pid_file
|
23
|
+
end
|
24
|
+
|
25
|
+
# send up info
|
26
|
+
on.condition(:lambda) do |c|
|
27
|
+
c.lambda = lambda do
|
28
|
+
puts 'yay I am up'
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# when process is down
|
35
|
+
w.transition(:down, :up) do |on|
|
36
|
+
# transition to 'up' if process comes up
|
37
|
+
on.condition(:process_running) do |c|
|
38
|
+
c.running = true
|
39
|
+
c.pid_file = $pid_file
|
40
|
+
end
|
41
|
+
|
42
|
+
# send down info
|
43
|
+
on.condition(:lambda) do |c|
|
44
|
+
c.lambda = lambda do
|
45
|
+
puts 'boo I am down'
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
if $0 == __FILE__
|
2
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. lib god])
|
3
|
+
end
|
4
|
+
|
5
|
+
RAILS_ROOT = "/Users/tom/dev/git/helloworld"
|
6
|
+
|
7
|
+
God.watch do |w|
|
8
|
+
w.name = "local-3000"
|
9
|
+
w.interval = 5 # seconds
|
10
|
+
w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -d"
|
11
|
+
w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
|
12
|
+
w.grace = 5
|
13
|
+
|
14
|
+
pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
|
15
|
+
|
16
|
+
# clean pid files before start if necessary
|
17
|
+
w.behavior(:clean_pid_file) do |b|
|
18
|
+
b.pid_file = pid_file
|
19
|
+
end
|
20
|
+
|
21
|
+
# start if process is not running
|
22
|
+
w.start_if do |start|
|
23
|
+
start.condition(:process_running) do |c|
|
24
|
+
c.running = false
|
25
|
+
c.pid_file = pid_file
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# restart if memory or cpu is too high
|
30
|
+
w.restart_if do |restart|
|
31
|
+
restart.condition(:memory_usage) do |c|
|
32
|
+
c.interval = 20
|
33
|
+
c.pid_file = pid_file
|
34
|
+
c.above = (50 * 1024) # 50mb
|
35
|
+
c.times = [3, 5]
|
36
|
+
end
|
37
|
+
|
38
|
+
restart.condition(:cpu_usage) do |c|
|
39
|
+
c.interval = 10
|
40
|
+
c.pid_file = pid_file
|
41
|
+
c.above = 10 # percent
|
42
|
+
c.times = [3, 5]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# clear old session files
|
48
|
+
# god.watch do |w|
|
49
|
+
# w.name = "local-session-cleanup"
|
50
|
+
# w.start = lambda do
|
51
|
+
# Dir["#{RAILS_ROOT}/tmp/sessions/ruby_sess.*"].select do |f|
|
52
|
+
# File.mtime(f) < Time.now - (7 * 24 * 60 * 60)
|
53
|
+
# end.each { |f| File.delete(f) }
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# w.start_if do |start|
|
57
|
+
# start.condition(:always)
|
58
|
+
# end
|
59
|
+
# end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
God.watch do |w|
|
2
|
+
w.name = 'running-load'
|
3
|
+
w.start = '/Users/tom/dev/god/test/configs/child_polls/simple_server.rb'
|
4
|
+
w.stop = ''
|
5
|
+
w.interval = 5
|
6
|
+
w.grace = 2
|
7
|
+
w.uid = 'tom'
|
8
|
+
w.gid = 'tom'
|
9
|
+
w.group = 'test'
|
10
|
+
|
11
|
+
w.start_if do |start|
|
12
|
+
start.condition(:process_running) do |c|
|
13
|
+
c.running = false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
God.watch do |w|
|
2
|
+
w.name = 'stop-options'
|
3
|
+
w.start = File.join(GOD_ROOT, *%w[test configs stop_options simple_server.rb])
|
4
|
+
w.stop_signal = 'USR1'
|
5
|
+
w.stop_timeout = 5
|
6
|
+
w.interval = 5
|
7
|
+
w.grace = 2
|
8
|
+
|
9
|
+
w.start_if do |start|
|
10
|
+
start.condition(:process_running) do |c|
|
11
|
+
c.running = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
w.restart_if do |restart|
|
16
|
+
restart.condition(:cpu_usage) do |c|
|
17
|
+
c.above = 30.percent
|
18
|
+
c.times = [3, 5]
|
19
|
+
end
|
20
|
+
|
21
|
+
restart.condition(:memory_usage) do |c|
|
22
|
+
c.above = 10.megabytes
|
23
|
+
c.times = [3, 5]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# lifecycle
|
28
|
+
w.lifecycle do |on|
|
29
|
+
on.condition(:flapping) do |c|
|
30
|
+
c.to_state = [:start, :restart]
|
31
|
+
c.times = 3
|
32
|
+
c.within = 60.seconds
|
33
|
+
c.transition = :unmonitored
|
34
|
+
c.retry_in = 10.seconds
|
35
|
+
c.retry_times = 2
|
36
|
+
c.retry_within = 5.minutes
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
('01'..'08').each do |i|
|
2
|
+
God.watch do |w|
|
3
|
+
w.name = "stress-#{i}"
|
4
|
+
w.start = "ruby " + File.join(File.dirname(__FILE__), *%w[simple_server.rb])
|
5
|
+
w.interval = 0
|
6
|
+
w.grace = 2
|
7
|
+
w.group = 'test'
|
8
|
+
|
9
|
+
w.start_if do |start|
|
10
|
+
start.condition(:process_running) do |c|
|
11
|
+
c.running = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
LOG_DIR = File.join(File.dirname(__FILE__), *%w[logs])
|
2
|
+
|
3
|
+
God.task do |t|
|
4
|
+
t.name = 'task'
|
5
|
+
t.valid_states = [:ok, :clean]
|
6
|
+
t.initial_state = :ok
|
7
|
+
t.interval = 5
|
8
|
+
|
9
|
+
# t.clean = lambda do
|
10
|
+
# Dir[File.join(LOG_DIR, '*.log')].each do |f|
|
11
|
+
# File.delete(f)
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
|
15
|
+
t.clean = "rm #{File.join(LOG_DIR, '*.log')}"
|
16
|
+
|
17
|
+
t.transition(:clean, :ok)
|
18
|
+
|
19
|
+
t.transition(:ok, :clean) do |on|
|
20
|
+
on.condition(:lambda) do |c|
|
21
|
+
c.lambda = lambda do
|
22
|
+
Dir[File.join(LOG_DIR, '*.log')].size > 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
ENV['GOD_TEST_RAILS_ROOT'] || abort("Set a rails root for testing in an environment variable called GOD_TEST_RAILS_ROOT")
|
2
|
+
|
3
|
+
RAILS_ROOT = ENV['GOD_TEST_RAILS_ROOT']
|
4
|
+
|
5
|
+
port = 5000
|
6
|
+
|
7
|
+
God.watch do |w|
|
8
|
+
w.name = "local-#{port}"
|
9
|
+
w.interval = 5.seconds
|
10
|
+
w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -p #{port} -d"
|
11
|
+
w.restart = "mongrel_rails restart -P ./log/mongrel.pid -c #{RAILS_ROOT}"
|
12
|
+
w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
|
13
|
+
w.group = 'mongrels'
|
14
|
+
w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
|
15
|
+
|
16
|
+
# clean pid files before start if necessary
|
17
|
+
w.behavior(:clean_pid_file)
|
18
|
+
|
19
|
+
# determine the state on startup
|
20
|
+
w.transition(:init, { true => :up, false => :start }) do |on|
|
21
|
+
on.condition(:process_running) do |c|
|
22
|
+
c.running = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# determine when process has finished starting
|
27
|
+
w.transition([:start, :restart], :up) do |on|
|
28
|
+
on.condition(:process_running) do |c|
|
29
|
+
c.running = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# start if process is not running
|
34
|
+
w.transition(:up, :start) do |on|
|
35
|
+
on.condition(:process_exits)
|
36
|
+
end
|
37
|
+
|
38
|
+
# restart if memory or cpu is too high
|
39
|
+
w.transition(:up, :restart) do |on|
|
40
|
+
on.condition(:memory_usage) do |c|
|
41
|
+
c.interval = 1
|
42
|
+
c.above = 50.megabytes
|
43
|
+
c.times = [3, 5]
|
44
|
+
end
|
45
|
+
|
46
|
+
on.condition(:cpu_usage) do |c|
|
47
|
+
c.interval = 1
|
48
|
+
c.above = 10.percent
|
49
|
+
c.times = [3, 5]
|
50
|
+
end
|
51
|
+
|
52
|
+
on.condition(:http_response_code) do |c|
|
53
|
+
c.host = 'localhost'
|
54
|
+
c.port = port
|
55
|
+
c.path = '/'
|
56
|
+
c.code_is_not = 200
|
57
|
+
c.timeout = 10.seconds
|
58
|
+
c.times = [3, 5]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__) # For use/testing when no gem is installed
|
2
|
+
|
3
|
+
# Use this flag to actually load all of the god infrastructure
|
4
|
+
$load_god = true
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib god sys_logger])
|
7
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib god])
|
8
|
+
God::EventHandler.load
|
9
|
+
|
10
|
+
require 'minitest/autorun'
|
11
|
+
require 'minitest/unit'
|
12
|
+
require 'set'
|
13
|
+
|
14
|
+
include God
|
15
|
+
|
16
|
+
if Process.uid != 0 and RbConfig::CONFIG['host_os'] == "linux"
|
17
|
+
abort <<-EOF
|
18
|
+
\n
|
19
|
+
*********************************************************************
|
20
|
+
* *
|
21
|
+
* You need to run these tests as root *
|
22
|
+
* chroot and netlink (linux only) require it *
|
23
|
+
* *
|
24
|
+
*********************************************************************
|
25
|
+
EOF
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'mocha/setup'
|
30
|
+
rescue LoadError
|
31
|
+
unless gems ||= false
|
32
|
+
require 'rubygems'
|
33
|
+
gems = true
|
34
|
+
retry
|
35
|
+
else
|
36
|
+
abort "=> You need the Mocha gem to run these tests."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module God
|
41
|
+
module Conditions
|
42
|
+
class FakeCondition < Condition
|
43
|
+
def test
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class FakePollCondition < PollCondition
|
49
|
+
def test
|
50
|
+
true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class FakeEventCondition < EventCondition
|
55
|
+
def register
|
56
|
+
end
|
57
|
+
def deregister
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Behaviors
|
63
|
+
class FakeBehavior < Behavior
|
64
|
+
def before_start
|
65
|
+
'foo'
|
66
|
+
end
|
67
|
+
def after_start
|
68
|
+
'bar'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module Contacts
|
74
|
+
class FakeContact < Contact
|
75
|
+
end
|
76
|
+
|
77
|
+
class InvalidContact
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.reset
|
82
|
+
self.watches = nil
|
83
|
+
self.groups = nil
|
84
|
+
self.server = nil
|
85
|
+
self.inited = nil
|
86
|
+
self.host = nil
|
87
|
+
self.port = nil
|
88
|
+
self.pid_file_directory = nil
|
89
|
+
self.registry.reset
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def silence_warnings
|
94
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
95
|
+
yield
|
96
|
+
ensure
|
97
|
+
$VERBOSE = old_verbose
|
98
|
+
end
|
99
|
+
|
100
|
+
LOG.instance_variable_set(:@io, StringIO.new())
|
101
|
+
|
102
|
+
def output_logs
|
103
|
+
io = LOG.instance_variable_get(:@io)
|
104
|
+
LOG.instance_variable_set(:@io, $stderr)
|
105
|
+
yield
|
106
|
+
ensure
|
107
|
+
LOG.instance_variable_set(:@io, io)
|
108
|
+
end
|
109
|
+
|
110
|
+
# module Kernel
|
111
|
+
# def abort(text)
|
112
|
+
# raise SystemExit, text
|
113
|
+
# end
|
114
|
+
# def exit(code)
|
115
|
+
# raise SystemExit, "Exit code: #{code}"
|
116
|
+
# end
|
117
|
+
# end
|
118
|
+
|
119
|
+
module Minitest::Assertions
|
120
|
+
def assert_abort
|
121
|
+
assert_raises SystemExit do
|
122
|
+
yield
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def assert_nothing_raised
|
127
|
+
yield
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# This allows you to be a good OOP citizen and honor encapsulation, but
|
132
|
+
# still make calls to private methods (for testing) by doing
|
133
|
+
#
|
134
|
+
# obj.bypass.private_thingie(arg1, arg2)
|
135
|
+
#
|
136
|
+
# Which is easier on the eye than
|
137
|
+
#
|
138
|
+
# obj.send(:private_thingie, arg1, arg2)
|
139
|
+
#
|
140
|
+
class Object
|
141
|
+
class Bypass
|
142
|
+
instance_methods.each do |m|
|
143
|
+
undef_method m unless m =~ /^(__|object_id)/
|
144
|
+
end
|
145
|
+
|
146
|
+
def initialize(ref)
|
147
|
+
@ref = ref
|
148
|
+
end
|
149
|
+
|
150
|
+
def method_missing(sym, *args)
|
151
|
+
@ref.__send__(sym, *args)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def bypass
|
156
|
+
Bypass.new(self)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Make sure we return valid exit codes
|
161
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION >= "1.9"
|
162
|
+
module Kernel
|
163
|
+
alias :__at_exit :at_exit
|
164
|
+
def at_exit(&block)
|
165
|
+
__at_exit do
|
166
|
+
exit_status = $!.status if $!.is_a?(SystemExit)
|
167
|
+
block.call
|
168
|
+
exit exit_status if exit_status
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|