god 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/History.txt +26 -0
  2. data/Manifest.txt +15 -1
  3. data/Rakefile +2 -7
  4. data/bin/god +104 -16
  5. data/lib/god.rb +169 -37
  6. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  7. data/lib/god/condition.rb +1 -0
  8. data/lib/god/conditions/degrading_lambda.rb +47 -0
  9. data/lib/god/conditions/process_exits.rb +6 -2
  10. data/lib/god/conditions/tries.rb +33 -0
  11. data/lib/god/dependency_graph.rb +41 -0
  12. data/lib/god/errors.rb +6 -0
  13. data/lib/god/hub.rb +43 -20
  14. data/lib/god/logger.rb +44 -0
  15. data/lib/god/process.rb +91 -19
  16. data/lib/god/registry.rb +4 -0
  17. data/lib/god/server.rb +12 -2
  18. data/lib/god/timeline.rb +36 -0
  19. data/lib/god/watch.rb +27 -8
  20. data/test/configs/child_events/child_events.god +7 -2
  21. data/test/configs/child_polls/child_polls.god +3 -1
  22. data/test/configs/child_polls/simple_server.rb +1 -1
  23. data/test/configs/daemon_events/daemon_events.god +7 -3
  24. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  25. data/test/configs/daemon_polls/simple_server.rb +6 -0
  26. data/test/configs/degrading_lambda/degrading_lambda.god +33 -0
  27. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  28. data/test/configs/real.rb +1 -1
  29. data/test/configs/running_load/running_load.god +16 -0
  30. data/test/configs/stress/simple_server.rb +3 -0
  31. data/test/configs/stress/stress.god +15 -0
  32. data/test/configs/test.rb +14 -2
  33. data/test/helper.rb +12 -2
  34. data/test/test_conditions_tries.rb +46 -0
  35. data/test/test_dependency_graph.rb +62 -0
  36. data/test/test_god.rb +289 -33
  37. data/test/test_handlers_kqueue_handler.rb +11 -7
  38. data/test/test_hub.rb +18 -0
  39. data/test/test_logger.rb +55 -0
  40. data/test/test_process.rb +135 -17
  41. data/test/test_registry.rb +2 -1
  42. data/test/test_server.rb +35 -4
  43. data/test/test_timeline.rb +14 -2
  44. data/test/test_watch.rb +7 -0
  45. metadata +21 -4
  46. data/lib/god/conditions/timeline.rb +0 -17
@@ -1,12 +1,16 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- class TestHandlersKqueueHandler < Test::Unit::TestCase
4
- def test_register_process
5
- KQueueHandler.expects(:monitor_process).with(1234, 2147483648)
6
- KQueueHandler.register_process(1234, [:proc_exit])
7
- end
3
+ if God::EventHandler.event_system == "kqueue"
4
+
5
+ class TestHandlersKqueueHandler < Test::Unit::TestCase
6
+ def test_register_process
7
+ KQueueHandler.expects(:monitor_process).with(1234, 2147483648)
8
+ KQueueHandler.register_process(1234, [:proc_exit])
9
+ end
8
10
 
9
- def test_events_mask
10
- assert_equal 2147483648, KQueueHandler.events_mask([:proc_exit])
11
+ def test_events_mask
12
+ assert_equal 2147483648, KQueueHandler.events_mask([:proc_exit])
13
+ end
11
14
  end
15
+
12
16
  end
data/test/test_hub.rb CHANGED
@@ -7,6 +7,7 @@ class TestHub < Test::Unit::TestCase
7
7
 
8
8
  God.watch do |w|
9
9
  w.name = 'foo'
10
+ w.start = 'bar'
10
11
  w.interval = 10
11
12
  end
12
13
 
@@ -139,6 +140,23 @@ class TestHub < Test::Unit::TestCase
139
140
  end
140
141
  end
141
142
 
143
+ def test_handle_poll_should_use_overridden_transition
144
+ c = Conditions::Tries.new
145
+ c.times = 1
146
+ c.transition = :start
147
+ c.prepare
148
+
149
+ m = Metric.new(@watch, {true => :up})
150
+ Hub.attach(c, m)
151
+
152
+ @watch.expects(:move).with(:start)
153
+
154
+ no_stdout do
155
+ t = Hub.handle_poll(c)
156
+ t.join
157
+ end
158
+ end
159
+
142
160
  # handle_event
143
161
 
144
162
  def test_handle_event_should_move
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestLogger < Test::Unit::TestCase
4
+ def setup
5
+ @log = God::Logger.new
6
+ end
7
+
8
+ # log
9
+
10
+ def test_log
11
+ @log.expects(:info).with("qux")
12
+
13
+ no_stdout do
14
+ @log.log(stub(:name => 'foo'), :info, "qux")
15
+ end
16
+
17
+ assert_equal 1, @log.logs.size
18
+ assert_instance_of Time, @log.logs['foo'][0][0]
19
+ assert_match(/qux/, @log.logs['foo'][0][1])
20
+ end
21
+
22
+ # watch_log_since
23
+
24
+ def test_watch_log_since
25
+ t1 = Time.now
26
+
27
+ no_stdout do
28
+ @log.log(stub(:name => 'foo'), :info, "one")
29
+ @log.log(stub(:name => 'foo'), :info, "two")
30
+ end
31
+
32
+ assert_match(/one.*two/m, @log.watch_log_since('foo', t1))
33
+
34
+ t2 = Time.now
35
+
36
+ no_stdout do
37
+ @log.log(stub(:name => 'foo'), :info, "three")
38
+ end
39
+
40
+ out = @log.watch_log_since('foo', t2)
41
+
42
+ assert_no_match(/one/, out)
43
+ assert_no_match(/two/, out)
44
+ assert_match(/three/, out)
45
+ end
46
+
47
+ # regular methods
48
+
49
+ def test_fatal
50
+ no_stdout do
51
+ @log.fatal('foo')
52
+ end
53
+ assert_equal 0, @log.logs.size
54
+ end
55
+ end
data/test/test_process.rb CHANGED
@@ -12,14 +12,134 @@ module God
12
12
  end
13
13
  end
14
14
 
15
- class TestProcess < Test::Unit::TestCase
15
+ class TestProcessChild < Test::Unit::TestCase
16
16
  def setup
17
- @p = God::Process.new(:name => 'foo', :pid_file => 'blah.pid')
17
+ God.internal_init
18
+ @p = God::Process.new
19
+ @p.name = 'foo'
18
20
  @p.stubs(:test).returns true # so we don't try to mkdir_p
19
21
  Process.stubs(:detach) # because we stub fork
20
22
  end
21
23
 
24
+ # valid?
25
+
26
+ def test_valid_should_return_true_if_auto_daemonized_and_log
27
+ @p.start = 'qux'
28
+ @p.log = 'bar'
29
+
30
+ assert @p.valid?
31
+ end
32
+
33
+ def test_valid_should_return_true_if_auto_daemonized_and_no_stop
34
+ @p.start = 'qux'
35
+ @p.log = 'bar'
36
+
37
+ assert @p.valid?
38
+ end
39
+
40
+ def test_valid_should_return_true_if_uid_exists
41
+ @p.start = 'qux'
42
+ @p.log = 'bar'
43
+ @p.uid = 'root'
44
+
45
+ assert @p.valid?
46
+ end
47
+
48
+ def test_valid_should_return_true_if_uid_does_not_exists
49
+ @p.start = 'qux'
50
+ @p.log = 'bar'
51
+ @p.uid = 'foobarbaz'
52
+
53
+ no_stdout do
54
+ assert !@p.valid?
55
+ end
56
+ end
57
+
58
+ def test_valid_should_return_true_if_gid_exists
59
+ @p.start = 'qux'
60
+ @p.log = 'bar'
61
+ @p.gid = 'wheel'
62
+
63
+ assert @p.valid?
64
+ end
65
+
66
+ def test_valid_should_return_true_if_gid_does_not_exists
67
+ @p.start = 'qux'
68
+ @p.log = 'bar'
69
+ @p.gid = 'foobarbaz'
70
+
71
+ no_stdout do
72
+ assert !@p.valid?
73
+ end
74
+ end
75
+ end
76
+
77
+ class TestProcessDaemon < Test::Unit::TestCase
78
+ def setup
79
+ God.internal_init
80
+ @p = God::Process.new
81
+ @p.name = 'foo'
82
+ @p.pid_file = 'blah.pid'
83
+ @p.stubs(:test).returns true # so we don't try to mkdir_p
84
+ Process.stubs(:detach) # because we stub fork
85
+ end
86
+
87
+ # alive?
88
+
89
+ def test_alive_should_call_system_process_exists
90
+ File.expects(:read).with('blah.pid').returns('1234')
91
+ System::Process.any_instance.expects(:exists?).returns(false)
92
+ assert !@p.alive?
93
+ end
94
+
95
+ # valid?
96
+
97
+ def test_valid_should_return_false_if_no_name
98
+ @p.name = nil
99
+ @p.start = 'bar'
100
+ @p.stop = 'baz'
101
+ no_stdout do
102
+ assert !@p.valid?
103
+ end
104
+ end
105
+
106
+ def test_valid_should_return_false_if_no_start
107
+ @p.name = 'foo'
108
+ @p.stop = 'baz'
109
+ no_stdout do
110
+ assert !@p.valid?
111
+ end
112
+ end
113
+
114
+ def test_valid_should_return_false_if_self_daemonized_and_no_stop
115
+ @p.start = 'bar'
116
+ @p.pid_file = 'foo'
117
+
118
+ no_stdout do
119
+ assert !@p.valid?
120
+ end
121
+ end
122
+
123
+ def test_valid_should_return_false_if_self_daemonized_and_log
124
+ @p.pid_file = 'foo'
125
+ @p.start = 'baz'
126
+ @p.stop = 'qux'
127
+ @p.log = 'bar'
128
+
129
+ no_stdout do
130
+ assert !@p.valid?
131
+ end
132
+ end
133
+
134
+ # defaul_pid_file
135
+
136
+ def test_default_pid_file
137
+ assert_equal File.join(God.pid_file_directory, 'foo.pid'), @p.default_pid_file
138
+ end
139
+
140
+ # call_action
22
141
  # These actually excercise call_action in the back at this point - Kev
142
+
23
143
  def test_call_action_with_string_should_fork_exec
24
144
  @p.start = "do something"
25
145
  IO.expects(:pipe).returns([StringIO.new('1234'), StringIO.new])
@@ -34,15 +154,12 @@ class TestProcess < Test::Unit::TestCase
34
154
  @p.start = cmd
35
155
  @p.call_action(:start)
36
156
  end
37
-
38
- def test_default_pid_file
39
- assert_equal File.join(God.pid_file_directory, 'foo.pid'), @p.default_pid_file
40
- end
41
157
 
42
158
  def test_call_action_without_pid_should_write_pid
43
159
  # Only for start, restart
44
160
  [:start, :restart].each do |action|
45
- @p = God::Process.new(:name => 'foo')
161
+ @p = God::Process.new
162
+ @p.name = 'foo'
46
163
  @p.stubs(:test).returns true
47
164
  IO.expects(:pipe).returns([StringIO.new('1234'), StringIO.new])
48
165
  @p.expects(:fork)
@@ -63,18 +180,19 @@ class TestProcess < Test::Unit::TestCase
63
180
  @p.call_action(:stop)
64
181
  end
65
182
 
66
- def test_call_action_should_mkdir_p_if_pid_file_dir_existence_test_fails
67
- @p.pid_file = nil
68
- IO.expects(:pipe).returns([StringIO.new('1234'), StringIO.new])
69
- @p.expects(:fork)
70
- Process.expects(:waitpid)
71
- @p.expects(:test).returns(false, true)
72
- FileUtils.expects(:mkdir_p).with(God.pid_file_directory)
73
- File.expects(:open)
74
- @p.start = "starting"
75
- @p.call_action(:start)
183
+ def test_call_action_with_invalid_command_class_should_raise
184
+ @p.start = 5
185
+ @p.stop = 'baz'
186
+
187
+ assert @p.valid?
188
+
189
+ assert_raise NotImplementedError do
190
+ @p.call_action(:start)
191
+ end
76
192
  end
77
193
 
194
+ # start!/stop!/restart!
195
+
78
196
  def test_start_stop_restart_bang
79
197
  [:start, :stop, :restart].each do |x|
80
198
  @p.expects(:call_action).with(x)
@@ -6,7 +6,8 @@ class TestRegistry < Test::Unit::TestCase
6
6
  end
7
7
 
8
8
  def test_add
9
- foo = God::Process.new(:name => 'foo')
9
+ foo = God::Process.new
10
+ foo.name = 'foo'
10
11
  God.registry.add(foo)
11
12
  assert_equal 1, God.registry.size
12
13
  assert_equal foo, God.registry['foo']
data/test/test_server.rb CHANGED
@@ -9,17 +9,48 @@ class TestServer < Test::Unit::TestCase
9
9
 
10
10
  def test_should_start_a_drb_server
11
11
  DRb.expects(:start_service)
12
- Server.new
12
+ no_stdout do
13
+ Server.new
14
+ end
13
15
  end
14
16
 
15
17
  def test_should_use_supplied_port_and_host
16
18
  DRb.expects(:start_service).with { |uri, object| uri == "druby://host:port" && object.is_a?(Server) }
17
- server = Server.new('host', 'port')
19
+ no_stdout do
20
+ server = Server.new('host', 'port')
21
+ end
18
22
  end
19
23
 
20
- def test_should_forward_foreign_method_calls_to_meddle
21
- server = Server.new
24
+ def test_should_forward_foreign_method_calls_to_god
25
+ server = nil
26
+ no_stdout do
27
+ server = Server.new
28
+ end
22
29
  God.expects(:send).with(:something_random)
23
30
  server.something_random
24
31
  end
32
+
33
+ def test_should_install_deny_all_by_default
34
+ ACL.expects(:new).with(%w{deny all})
35
+ no_stdout do
36
+ Server.new
37
+ end
38
+ end
39
+
40
+ def test_should_install_pass_through_acl
41
+ ACL.expects(:new).with(%w{deny all allow 127.0.0.1 allow 0.0.0.0})
42
+ no_stdout do
43
+ Server.new(nil, 17165, %w{127.0.0.1 0.0.0.0})
44
+ end
45
+ end
46
+
47
+ # ping
48
+
49
+ def test_ping_should_return_true
50
+ server = nil
51
+ no_stdout do
52
+ server = Server.new
53
+ end
54
+ assert server.ping
55
+ end
25
56
  end
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/helper'
2
2
 
3
3
  class TestTimeline < Test::Unit::TestCase
4
4
  def setup
5
- @timeline = Conditions::Timeline.new(5)
5
+ @timeline = Timeline.new(5)
6
6
  end
7
7
 
8
8
  def test_new_should_be_empty
@@ -14,11 +14,23 @@ class TestTimeline < Test::Unit::TestCase
14
14
  @timeline.push(i)
15
15
  end
16
16
 
17
- assert_equal [10, 9, 8, 7, 6], @timeline
17
+ assert_equal [6, 7, 8, 9, 10], @timeline
18
18
  end
19
19
 
20
20
  def test_clear_should_clear_array
21
21
  @timeline.push(1)
22
22
  assert_equal [], @timeline.clear
23
23
  end
24
+
25
+ # def test_benchmark
26
+ # require 'benchmark'
27
+ #
28
+ # count = 1_000_000
29
+ #
30
+ # t = Timeline.new(10)
31
+ #
32
+ # Benchmark.bmbm do |x|
33
+ # x.report("go") { count.times { t.push(5) } }
34
+ # end
35
+ # end
24
36
  end
data/test/test_watch.rb CHANGED
@@ -41,6 +41,13 @@ class TestWatch < Test::Unit::TestCase
41
41
  assert_equal @watch.mutex, @watch.mutex
42
42
  end
43
43
 
44
+ # valid?
45
+
46
+ def test_valid?
47
+ God::Process.any_instance.expects(:valid?)
48
+ @watch.valid?
49
+ end
50
+
44
51
  # behavior
45
52
 
46
53
  def test_behavior_should_record_behavior
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: god
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.0
7
- date: 2007-08-17 00:00:00 -07:00
6
+ version: 0.4.0
7
+ date: 2007-09-10 00:00:00 -07:00
8
8
  summary: Like monit, only awesome
9
9
  require_paths:
10
10
  - lib
@@ -43,20 +43,24 @@ files:
43
43
  - lib/god.rb
44
44
  - lib/god/behavior.rb
45
45
  - lib/god/behaviors/clean_pid_file.rb
46
+ - lib/god/behaviors/notify_when_flapping.rb
46
47
  - lib/god/condition.rb
47
48
  - lib/god/conditions/always.rb
48
49
  - lib/god/conditions/cpu_usage.rb
50
+ - lib/god/conditions/degrading_lambda.rb
49
51
  - lib/god/conditions/lambda.rb
50
52
  - lib/god/conditions/memory_usage.rb
51
53
  - lib/god/conditions/process_exits.rb
52
54
  - lib/god/conditions/process_running.rb
53
- - lib/god/conditions/timeline.rb
55
+ - lib/god/conditions/tries.rb
56
+ - lib/god/dependency_graph.rb
54
57
  - lib/god/errors.rb
55
58
  - lib/god/event_handler.rb
56
59
  - lib/god/event_handlers/dummy_handler.rb
57
60
  - lib/god/event_handlers/kqueue_handler.rb
58
61
  - lib/god/event_handlers/netlink_handler.rb
59
62
  - lib/god/hub.rb
63
+ - lib/god/logger.rb
60
64
  - lib/god/metric.rb
61
65
  - lib/god/process.rb
62
66
  - lib/god/registry.rb
@@ -64,6 +68,7 @@ files:
64
68
  - lib/god/server.rb
65
69
  - lib/god/sugar.rb
66
70
  - lib/god/system/process.rb
71
+ - lib/god/timeline.rb
67
72
  - lib/god/timer.rb
68
73
  - lib/god/watch.rb
69
74
  - test/configs/child_events/child_events.god
@@ -72,17 +77,26 @@ files:
72
77
  - test/configs/child_polls/simple_server.rb
73
78
  - test/configs/daemon_events/daemon_events.god
74
79
  - test/configs/daemon_events/simple_server.rb
80
+ - test/configs/daemon_polls/daemon_polls.god
81
+ - test/configs/daemon_polls/simple_server.rb
82
+ - test/configs/degrading_lambda/degrading_lambda.god
83
+ - test/configs/degrading_lambda/tcp_server.rb
75
84
  - test/configs/real.rb
85
+ - test/configs/running_load/running_load.god
86
+ - test/configs/stress/simple_server.rb
87
+ - test/configs/stress/stress.god
76
88
  - test/configs/test.rb
77
89
  - test/helper.rb
78
90
  - test/suite.rb
79
91
  - test/test_behavior.rb
80
92
  - test/test_condition.rb
81
93
  - test/test_conditions_process_running.rb
94
+ - test/test_dependency_graph.rb
82
95
  - test/test_event_handler.rb
83
96
  - test/test_god.rb
84
97
  - test/test_handlers_kqueue_handler.rb
85
98
  - test/test_hub.rb
99
+ - test/test_logger.rb
86
100
  - test/test_metric.rb
87
101
  - test/test_process.rb
88
102
  - test/test_registry.rb
@@ -97,10 +111,13 @@ test_files:
97
111
  - test/test_behavior.rb
98
112
  - test/test_condition.rb
99
113
  - test/test_conditions_process_running.rb
114
+ - test/test_conditions_tries.rb
115
+ - test/test_dependency_graph.rb
100
116
  - test/test_event_handler.rb
101
117
  - test/test_god.rb
102
118
  - test/test_handlers_kqueue_handler.rb
103
119
  - test/test_hub.rb
120
+ - test/test_logger.rb
104
121
  - test/test_metric.rb
105
122
  - test/test_process.rb
106
123
  - test/test_registry.rb
@@ -132,5 +149,5 @@ dependencies:
132
149
  requirements:
133
150
  - - ">="
134
151
  - !ruby/object:Gem::Version
135
- version: 1.2.1
152
+ version: 1.3.0
136
153
  version: