monitr 0.0.1

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.
@@ -0,0 +1,246 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ module Monitr
4
+ class Process
5
+ # def fork
6
+ # raise "You forgot to stub fork"
7
+ # end
8
+
9
+ def exec(*args)
10
+ raise "You forgot to stub exec"
11
+ end
12
+ end
13
+ end
14
+
15
+ class TestProcessChild < Test::Unit::TestCase
16
+ def setup
17
+ Monitr.internal_init
18
+ @p = Monitr::Process.new
19
+ @p.name = 'foo'
20
+ @p.stubs(:test).returns true # so we don't try to mkdir_p
21
+ Process.stubs(:detach) # because we stub fork
22
+
23
+ ::Process::Sys.stubs(:setuid).returns(true)
24
+ ::Process::Sys.stubs(:setgid).returns(true)
25
+ end
26
+
27
+ # valid?
28
+
29
+ def test_valid_should_return_true_if_auto_daemonized_and_log
30
+ @p.start = 'qux'
31
+ @p.log = 'bar'
32
+
33
+ assert @p.valid?
34
+ end
35
+
36
+ def test_valid_should_return_true_if_auto_daemonized_and_no_stop
37
+ @p.start = 'qux'
38
+ @p.log = 'bar'
39
+
40
+ assert @p.valid?
41
+ end
42
+
43
+ def test_valid_should_return_true_if_uid_exists
44
+ @p.start = 'qux'
45
+ @p.log = '/tmp/foo.log'
46
+ @p.uid = 'root'
47
+
48
+ assert @p.valid?
49
+ end
50
+
51
+ def test_valid_should_return_true_if_uid_does_not_exists
52
+ @p.start = 'qux'
53
+ @p.log = '/tmp/foo.log'
54
+ @p.uid = 'foobarbaz'
55
+
56
+ no_stdout do
57
+ no_stderr do
58
+ assert !@p.valid?
59
+ end
60
+ end
61
+ end
62
+
63
+ def test_valid_should_return_true_if_gid_exists
64
+ @p.start = 'qux'
65
+ @p.log = '/tmp/foo.log'
66
+ @p.gid = 'wheel'
67
+
68
+ assert @p.valid?
69
+ end
70
+
71
+ def test_valid_should_return_false_if_gid_does_not_exists
72
+ @p.start = 'qux'
73
+ @p.log = '/tmp/foo.log'
74
+ @p.gid = 'foobarbaz'
75
+
76
+ no_stdout do
77
+ no_stderr do
78
+ assert !@p.valid?
79
+ end
80
+ end
81
+ end
82
+
83
+ def test_valid_should_return_false_with_bogus_chroot
84
+ @p.chroot = '/bogusroot'
85
+
86
+ no_stdout do
87
+ no_stderr do
88
+ assert !@p.valid?
89
+ end
90
+ end
91
+ end
92
+
93
+ def test_valid_should_return_true_with_chroot_and_valid_log
94
+ @p.start = 'qux'
95
+ @p.chroot = '/tmp'
96
+ @p.log = '/tmp/foo.log'
97
+
98
+ File.expects(:exist?).with('/tmp').returns(true)
99
+ File.expects(:exist?).with('/tmp/foo.log').returns(true)
100
+ File.expects(:exist?).with('/tmp/dev/null').returns(true)
101
+
102
+ assert @p.valid?
103
+ end
104
+
105
+ # call_action
106
+
107
+ def test_call_action_should_write_pid
108
+ # Only for start, restart
109
+ [:start, :restart].each do |action|
110
+ @p.stubs(:test).returns true
111
+ IO.expects(:pipe).returns([StringIO.new('1234'), StringIO.new])
112
+ @p.expects(:fork)
113
+ Process.expects(:waitpid)
114
+ File.expects(:open).with(@p.default_pid_file, 'w')
115
+ @p.send("#{action}=", "run")
116
+ @p.call_action(action)
117
+ end
118
+ end
119
+ end
120
+
121
+ ###############################################################################
122
+ #
123
+ # Daemon
124
+ #
125
+ ###############################################################################
126
+
127
+ class TestProcessDaemon < Test::Unit::TestCase
128
+ def setup
129
+ Monitr.internal_init
130
+ @p = Monitr::Process.new
131
+ @p.name = 'foo'
132
+ @p.pid_file = 'blah.pid'
133
+ @p.stubs(:test).returns true # so we don't try to mkdir_p
134
+ Process.stubs(:detach) # because we stub fork
135
+ end
136
+
137
+ # alive?
138
+
139
+ def test_alive_should_call_system_process_exists
140
+ File.expects(:read).with('blah.pid').times(2).returns('1234')
141
+ System::Process.any_instance.expects(:exists?).returns(false)
142
+ assert !@p.alive?
143
+ end
144
+
145
+ def test_alive_should_return_false_if_no_such_file
146
+ File.expects(:read).with('blah.pid').raises(Errno::ENOENT)
147
+ assert !@p.alive?
148
+ end
149
+
150
+ # valid?
151
+
152
+ def test_valid_should_return_false_if_no_start
153
+ @p.name = 'foo'
154
+ @p.stop = 'baz'
155
+ no_stdout do
156
+ assert !@p.valid?
157
+ end
158
+ end
159
+
160
+ def test_valid_should_return_false_if_self_daemonized_and_no_stop
161
+ @p.start = 'bar'
162
+ @p.pid_file = 'foo'
163
+
164
+ no_stdout do
165
+ assert !@p.valid?
166
+ end
167
+ end
168
+
169
+ # pid
170
+
171
+ def test_pid_should_return_integer_for_valid_pid_files
172
+ File.stubs(:read).returns("123")
173
+ assert_equal 123, @p.pid
174
+ end
175
+
176
+ def test_pid_should_return_nil_for_missing_files
177
+ @p.pid_file = ''
178
+ assert_equal nil, @p.pid
179
+ end
180
+
181
+ def test_pid_should_return_nil_for_invalid_pid_files
182
+ File.stubs(:read).returns("four score and seven years ago")
183
+ assert_equal nil, @p.pid
184
+ end
185
+
186
+ def test_pid_should_retain_last_pid_value_if_pid_file_is_removed
187
+ File.stubs(:read).returns("123")
188
+ assert_equal 123, @p.pid
189
+
190
+ File.stubs(:read).raises(Errno::ENOENT)
191
+ assert_equal 123, @p.pid
192
+
193
+ File.stubs(:read).returns("246")
194
+ assert_equal 246, @p.pid
195
+ end
196
+
197
+ # default_pid_file
198
+
199
+ def test_default_pid_file
200
+ assert_equal File.join(Monitr.pid_file_directory, 'foo.pid'), @p.default_pid_file
201
+ end
202
+
203
+ # unix socket
204
+
205
+ def test_unix_socket_should_return_path_specified
206
+ @p.unix_socket = '/path/to-socket'
207
+ assert_equal '/path/to-socket', @p.unix_socket
208
+ end
209
+
210
+ # call_action
211
+ # These actually excercise call_action in the back at this point - Kev
212
+
213
+ def test_call_action_with_string_should_call_system
214
+ @p.start = "do something"
215
+ @p.expects(:fork)
216
+ Process.expects(:waitpid2).returns([123, 0])
217
+ @p.call_action(:start)
218
+ end
219
+
220
+ def test_call_action_with_lambda_should_call
221
+ cmd = lambda { puts "Hi" }
222
+ cmd.expects(:call)
223
+ @p.start = cmd
224
+ @p.call_action(:start)
225
+ end
226
+
227
+ def test_call_action_with_invalid_command_class_should_raise
228
+ @p.start = 5
229
+ @p.stop = 'baz'
230
+
231
+ assert @p.valid?
232
+
233
+ assert_raise NotImplementedError do
234
+ @p.call_action(:start)
235
+ end
236
+ end
237
+
238
+ # start!/stop!/restart!
239
+
240
+ def test_start_stop_restart_bang
241
+ [:start, :stop, :restart].each do |x|
242
+ @p.expects(:call_action).with(x)
243
+ @p.send("#{x}!")
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestRegistry < Test::Unit::TestCase
4
+ def setup
5
+ Monitr.registry.reset
6
+ end
7
+
8
+ def test_add
9
+ foo = Monitr::Process.new
10
+ foo.name = 'foo'
11
+ Monitr.registry.add(foo)
12
+ assert_equal 1, Monitr.registry.size
13
+ assert_equal foo, Monitr.registry['foo']
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSocket < Test::Unit::TestCase
4
+ def setup
5
+ silence_warnings do
6
+ Object.const_set(:DRb, stub_everything)
7
+ end
8
+ end
9
+
10
+ def test_should_start_a_drb_server
11
+ DRb.expects(:start_service)
12
+ no_stdout do
13
+ Monitr::Socket.new
14
+ end
15
+ end
16
+
17
+ def test_should_use_supplied_port_and_host
18
+ DRb.expects(:start_service).with { |uri, object| uri == "drbunix:///tmp/monitr.9999.sock" && object.is_a?(Monitr::Socket) }
19
+ no_stdout do
20
+ server = Monitr::Socket.new(9999)
21
+ end
22
+ end
23
+
24
+ def test_should_forward_foreign_method_calls_to_monitr
25
+ server = nil
26
+ no_stdout do
27
+ server = Monitr::Socket.new
28
+ end
29
+ Monitr.expects(:send).with(:something_random)
30
+ server.something_random
31
+ end
32
+
33
+ # ping
34
+
35
+ def test_ping_should_return_true
36
+ server = nil
37
+ no_stdout do
38
+ server = Monitr::Socket.new
39
+ end
40
+ assert server.ping
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSugar < Test::Unit::TestCase
4
+ def test_seconds
5
+ assert_equal 1, 1.seconds
6
+ assert_equal 1, 1.second
7
+ end
8
+
9
+ def test_minutes
10
+ assert_equal 60, 1.minutes
11
+ assert_equal 60, 1.minute
12
+ end
13
+
14
+ def test_hours
15
+ assert_equal 3600, 1.hours
16
+ assert_equal 3600, 1.hour
17
+ end
18
+
19
+ def test_days
20
+ assert_equal 86400, 1.days
21
+ assert_equal 86400, 1.day
22
+ end
23
+
24
+ def test_kilobytes
25
+ assert_equal 1, 1.kilobytes
26
+ assert_equal 1, 1.kilobyte
27
+ end
28
+
29
+ def test_megabytes
30
+ assert_equal 1024, 1.megabytes
31
+ assert_equal 1024, 1.megabyte
32
+ end
33
+
34
+ def test_gigabytes
35
+ assert_equal 1024 ** 2, 1.gigabytes
36
+ assert_equal 1024 ** 2, 1.gigabyte
37
+ end
38
+
39
+ def test_percent
40
+ assert_equal 1, 1.percent
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSystemPortablePoller < Test::Unit::TestCase
4
+ def setup
5
+ pid = Process.pid
6
+ @process = System::PortablePoller.new(pid)
7
+ end
8
+
9
+ def test_time_string_to_seconds
10
+ assert_equal 0, @process.bypass.time_string_to_seconds('0:00:00')
11
+ assert_equal 0, @process.bypass.time_string_to_seconds('0:00:55')
12
+ assert_equal 27, @process.bypass.time_string_to_seconds('0:27:32')
13
+ assert_equal 75, @process.bypass.time_string_to_seconds('1:15:13')
14
+ assert_equal 735, @process.bypass.time_string_to_seconds('12:15:13')
15
+ end
16
+ end
17
+
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSystemProcess < Test::Unit::TestCase
4
+ def setup
5
+ pid = Process.pid
6
+ @process = System::Process.new(pid)
7
+ end
8
+
9
+ def test_exists_should_return_true_for_running_process
10
+ assert_equal true, @process.exists?
11
+ end
12
+
13
+ def test_exists_should_return_false_for_non_existant_process
14
+ assert_equal false, System::Process.new(9999999).exists?
15
+ end
16
+
17
+ def test_memory
18
+ assert_kind_of Integer, @process.memory
19
+ assert @process.memory > 0
20
+ end
21
+
22
+ def test_percent_memory
23
+ assert_kind_of Float, @process.percent_memory
24
+ end
25
+
26
+ def test_percent_cpu
27
+ assert_kind_of Float, @process.percent_cpu
28
+ end
29
+ end
30
+
@@ -0,0 +1,262 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTask < Test::Unit::TestCase
4
+ def setup
5
+ Monitr.internal_init
6
+ @task = Task.new
7
+ @task.name = 'foo'
8
+ @task.valid_states = [:foo, :bar]
9
+ @task.initial_state = :foo
10
+ @task.interval = 5
11
+ @task.prepare
12
+ end
13
+
14
+ # valid?
15
+
16
+ def test_valid_should_return_false_if_no_name
17
+ @task.name = nil
18
+ no_stdout do
19
+ assert !@task.valid?
20
+ end
21
+ end
22
+
23
+ def test_valid_should_return_false_if_no_valid_states
24
+ @task.valid_states = nil
25
+ no_stdout do
26
+ assert !@task.valid?
27
+ end
28
+ end
29
+
30
+ def test_valid_should_return_false_if_no_initial_state
31
+ @task.initial_state = nil
32
+ no_stdout do
33
+ assert !@task.valid?
34
+ end
35
+ end
36
+
37
+ # transition
38
+
39
+ def test_transition_should_be_always_if_no_block_was_given
40
+ @task.transition(:foo, :bar)
41
+
42
+ assert 1, @task.metrics.size
43
+ assert Conditions::Always, @task.metrics.keys.first.class
44
+ end
45
+
46
+ # method_missing
47
+
48
+ def test_method_missing_should_create_accessor_for_states
49
+ assert_nothing_raised do
50
+ @task.foo = 'testing'
51
+ end
52
+ end
53
+
54
+ def test_method_missing_should_raise_for_non_states
55
+ assert_raise NoMethodError do
56
+ @task.baz = 5
57
+ end
58
+ end
59
+
60
+ def test_method_missing_should_raise_for_non_setters
61
+ assert_raise NoMethodError do
62
+ @task.baz
63
+ end
64
+ end
65
+
66
+ # action
67
+
68
+ def test_action_should_send_string_commands_to_system
69
+ @task.foo = 'foo'
70
+ Thread.current.stubs(:==).returns(true)
71
+ @task.expects(:system).with('foo')
72
+ no_stdout { @task.action(:foo, nil) }
73
+ end
74
+
75
+ def test_action_should_call_lambda_commands
76
+ @task.foo = lambda { }
77
+ Thread.current.stubs(:==).returns(true)
78
+ @task.foo.expects(:call)
79
+ no_stdout { @task.action(:foo, nil) }
80
+ end
81
+
82
+ def test_action_should_raise_not_implemented_on_non_string_or_lambda_action
83
+ Thread.current.stubs(:==).returns(true)
84
+ assert_raise NotImplementedError do
85
+ @task.foo = 7
86
+ @task.action(:foo, nil)
87
+ end
88
+ end
89
+
90
+ def test_action_from_outside_driver_should_send_message_to_driver
91
+ @task.foo = 'foo'
92
+ @task.driver.expects(:message).with(:action, [:foo, nil])
93
+ @task.action(:foo, nil)
94
+ end
95
+
96
+ # attach
97
+
98
+ def test_attach_should_schedule_for_poll_condition
99
+ c = Conditions::FakePollCondition.new
100
+ @task.driver.expects(:schedule).with(c, 0)
101
+ @task.attach(c)
102
+ end
103
+
104
+ def test_attach_should_regsiter_for_event_condition
105
+ c = Conditions::FakeEventCondition.new
106
+ c.expects(:register)
107
+ @task.attach(c)
108
+ end
109
+
110
+ # detach
111
+
112
+ def test_detach_should_reset_poll_condition
113
+ c = Conditions::FakePollCondition.new
114
+ c.expects(:reset)
115
+ c.expects(:deregister).never
116
+ @task.detach(c)
117
+ end
118
+
119
+ def test_detach_should_deregister_event_conditions
120
+ c = Conditions::FakeEventCondition.new
121
+ c.expects(:deregister).once
122
+ @task.detach(c)
123
+ end
124
+
125
+ # trigger
126
+
127
+ def test_trigger_should_send_message_to_driver
128
+ c = Conditions::FakePollCondition.new
129
+ @task.driver.expects(:message).with(:handle_event, [c])
130
+ @task.trigger(c)
131
+ end
132
+
133
+ # handle_poll
134
+
135
+ def test_handle_poll_no_change_should_reschedule
136
+ c = Conditions::FakePollCondition.new
137
+ c.watch = @task
138
+ c.interval = 10
139
+
140
+ m = Metric.new(@task, {true => :up})
141
+ @task.directory[c] = m
142
+
143
+ c.expects(:test).returns(false)
144
+ @task.driver.expects(:schedule)
145
+
146
+ no_stdout do
147
+ @task.handle_poll(c)
148
+ end
149
+ end
150
+
151
+ def test_handle_poll_change_should_move
152
+ c = Conditions::FakePollCondition.new
153
+ c.watch = @task
154
+ c.interval = 10
155
+
156
+ m = Metric.new(@task, {true => :up})
157
+ @task.directory[c] = m
158
+
159
+ c.expects(:test).returns(true)
160
+ @task.expects(:move).with(:up)
161
+
162
+ no_stdout do
163
+ @task.handle_poll(c)
164
+ end
165
+ end
166
+
167
+ def test_handle_poll_should_use_overridden_transition
168
+ c = Conditions::Tries.new
169
+ c.watch = @task
170
+ c.times = 1
171
+ c.transition = :start
172
+ c.prepare
173
+
174
+ m = Metric.new(@task, {true => :up})
175
+ @task.directory[c] = m
176
+
177
+ @task.expects(:move).with(:start)
178
+
179
+ no_stdout do
180
+ @task.handle_poll(c)
181
+ end
182
+ end
183
+
184
+ def test_handle_poll_should_notify_if_triggering
185
+ c = Conditions::FakePollCondition.new
186
+ c.watch = @task
187
+ c.interval = 10
188
+ c.notify = 'tom'
189
+
190
+ m = Metric.new(@task, {true => :up})
191
+ @task.directory[c] = m
192
+
193
+ c.expects(:test).returns(true)
194
+ @task.expects(:notify)
195
+
196
+ no_stdout do
197
+ @task.handle_poll(c)
198
+ end
199
+ end
200
+
201
+ def test_handle_poll_should_not_notify_if_not_triggering
202
+ c = Conditions::FakePollCondition.new
203
+ c.watch = @task
204
+ c.interval = 10
205
+ c.notify = 'tom'
206
+
207
+ m = Metric.new(@task, {true => :up})
208
+ @task.directory[c] = m
209
+
210
+ c.expects(:test).returns(false)
211
+ @task.expects(:notify).never
212
+
213
+ no_stdout do
214
+ @task.handle_poll(c)
215
+ end
216
+ end
217
+
218
+ # handle_event
219
+
220
+ def test_handle_event_should_move
221
+ c = Conditions::FakeEventCondition.new
222
+ c.watch = @task
223
+
224
+ m = Metric.new(@task, {true => :up})
225
+ @task.directory[c] = m
226
+
227
+ @task.expects(:move).with(:up)
228
+
229
+ no_stdout do
230
+ @task.handle_event(c)
231
+ end
232
+ end
233
+
234
+ def test_handle_event_should_notify_if_triggering
235
+ c = Conditions::FakeEventCondition.new
236
+ c.watch = @task
237
+ c.notify = 'tom'
238
+
239
+ m = Metric.new(@task, {true => :up})
240
+ @task.directory[c] = m
241
+
242
+ @task.expects(:notify)
243
+
244
+ no_stdout do
245
+ @task.handle_event(c)
246
+ end
247
+ end
248
+
249
+ def test_handle_event_should_not_notify_if_no_notify_set
250
+ c = Conditions::FakeEventCondition.new
251
+ c.watch = @task
252
+
253
+ m = Metric.new(@task, {true => :up})
254
+ @task.directory[c] = m
255
+
256
+ @task.expects(:notify).never
257
+
258
+ no_stdout do
259
+ @task.handle_event(c)
260
+ end
261
+ end
262
+ end