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.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/Announce.txt +135 -0
  3. data/Gemfile +9 -0
  4. data/History.txt +469 -0
  5. data/LICENSE +22 -0
  6. data/README.md +37 -0
  7. data/Rakefile +185 -0
  8. data/TODO.md +37 -0
  9. data/bin/mcproc +134 -0
  10. data/doc/intro.asciidoc +20 -0
  11. data/doc/mcproc.asciidoc +1592 -0
  12. data/ext/god/.gitignore +5 -0
  13. data/ext/god/extconf.rb +56 -0
  14. data/ext/god/kqueue_handler.c +133 -0
  15. data/ext/god/netlink_handler.c +182 -0
  16. data/lib/god.rb +780 -0
  17. data/lib/god/behavior.rb +52 -0
  18. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  19. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  20. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  21. data/lib/god/cli/command.rb +268 -0
  22. data/lib/god/cli/run.rb +170 -0
  23. data/lib/god/cli/version.rb +23 -0
  24. data/lib/god/compat19.rb +33 -0
  25. data/lib/god/condition.rb +96 -0
  26. data/lib/god/conditions/always.rb +36 -0
  27. data/lib/god/conditions/complex.rb +86 -0
  28. data/lib/god/conditions/cpu_usage.rb +80 -0
  29. data/lib/god/conditions/degrading_lambda.rb +52 -0
  30. data/lib/god/conditions/disk_usage.rb +32 -0
  31. data/lib/god/conditions/file_mtime.rb +28 -0
  32. data/lib/god/conditions/file_touched.rb +44 -0
  33. data/lib/god/conditions/flapping.rb +128 -0
  34. data/lib/god/conditions/http_response_code.rb +184 -0
  35. data/lib/god/conditions/lambda.rb +25 -0
  36. data/lib/god/conditions/memory_usage.rb +82 -0
  37. data/lib/god/conditions/process_exits.rb +66 -0
  38. data/lib/god/conditions/process_running.rb +63 -0
  39. data/lib/god/conditions/socket_responding.rb +142 -0
  40. data/lib/god/conditions/tries.rb +44 -0
  41. data/lib/god/configurable.rb +57 -0
  42. data/lib/god/contact.rb +114 -0
  43. data/lib/god/contacts/airbrake.rb +44 -0
  44. data/lib/god/contacts/campfire.rb +121 -0
  45. data/lib/god/contacts/email.rb +130 -0
  46. data/lib/god/contacts/hipchat.rb +117 -0
  47. data/lib/god/contacts/jabber.rb +75 -0
  48. data/lib/god/contacts/prowl.rb +57 -0
  49. data/lib/god/contacts/scout.rb +55 -0
  50. data/lib/god/contacts/sensu.rb +59 -0
  51. data/lib/god/contacts/slack.rb +98 -0
  52. data/lib/god/contacts/statsd.rb +46 -0
  53. data/lib/god/contacts/twitter.rb +51 -0
  54. data/lib/god/contacts/webhook.rb +74 -0
  55. data/lib/god/driver.rb +238 -0
  56. data/lib/god/errors.rb +24 -0
  57. data/lib/god/event_handler.rb +112 -0
  58. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  59. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  60. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  61. data/lib/god/logger.rb +109 -0
  62. data/lib/god/metric.rb +87 -0
  63. data/lib/god/process.rb +381 -0
  64. data/lib/god/registry.rb +32 -0
  65. data/lib/god/simple_logger.rb +59 -0
  66. data/lib/god/socket.rb +113 -0
  67. data/lib/god/sugar.rb +62 -0
  68. data/lib/god/sys_logger.rb +45 -0
  69. data/lib/god/system/portable_poller.rb +42 -0
  70. data/lib/god/system/process.rb +50 -0
  71. data/lib/god/system/slash_proc_poller.rb +92 -0
  72. data/lib/god/task.rb +552 -0
  73. data/lib/god/timeline.rb +25 -0
  74. data/lib/god/trigger.rb +43 -0
  75. data/lib/god/watch.rb +340 -0
  76. data/mcproc.gemspec +192 -0
  77. data/test/configs/child_events/child_events.god +44 -0
  78. data/test/configs/child_events/simple_server.rb +3 -0
  79. data/test/configs/child_polls/child_polls.god +37 -0
  80. data/test/configs/child_polls/simple_server.rb +12 -0
  81. data/test/configs/complex/complex.god +59 -0
  82. data/test/configs/complex/simple_server.rb +3 -0
  83. data/test/configs/contact/contact.god +118 -0
  84. data/test/configs/contact/simple_server.rb +3 -0
  85. data/test/configs/daemon_events/daemon_events.god +37 -0
  86. data/test/configs/daemon_events/simple_server.rb +8 -0
  87. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  88. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  89. data/test/configs/daemon_polls/simple_server.rb +6 -0
  90. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  91. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  92. data/test/configs/keepalive/keepalive.god +9 -0
  93. data/test/configs/keepalive/keepalive.rb +12 -0
  94. data/test/configs/lifecycle/lifecycle.god +25 -0
  95. data/test/configs/matias/matias.god +50 -0
  96. data/test/configs/real.rb +59 -0
  97. data/test/configs/running_load/running_load.god +16 -0
  98. data/test/configs/stop_options/simple_server.rb +12 -0
  99. data/test/configs/stop_options/stop_options.god +39 -0
  100. data/test/configs/stress/simple_server.rb +3 -0
  101. data/test/configs/stress/stress.god +15 -0
  102. data/test/configs/task/logs/.placeholder +0 -0
  103. data/test/configs/task/task.god +26 -0
  104. data/test/configs/test.rb +61 -0
  105. data/test/configs/usr1_trapper.rb +10 -0
  106. data/test/helper.rb +172 -0
  107. data/test/suite.rb +6 -0
  108. data/test/test_airbrake.rb +14 -0
  109. data/test/test_behavior.rb +18 -0
  110. data/test/test_campfire.rb +22 -0
  111. data/test/test_condition.rb +52 -0
  112. data/test/test_conditions_disk_usage.rb +50 -0
  113. data/test/test_conditions_http_response_code.rb +109 -0
  114. data/test/test_conditions_process_running.rb +40 -0
  115. data/test/test_conditions_socket_responding.rb +176 -0
  116. data/test/test_conditions_tries.rb +67 -0
  117. data/test/test_contact.rb +109 -0
  118. data/test/test_driver.rb +26 -0
  119. data/test/test_email.rb +34 -0
  120. data/test/test_event_handler.rb +82 -0
  121. data/test/test_god.rb +710 -0
  122. data/test/test_god_system.rb +201 -0
  123. data/test/test_handlers_kqueue_handler.rb +16 -0
  124. data/test/test_hipchat.rb +23 -0
  125. data/test/test_jabber.rb +29 -0
  126. data/test/test_logger.rb +55 -0
  127. data/test/test_metric.rb +74 -0
  128. data/test/test_process.rb +263 -0
  129. data/test/test_prowl.rb +15 -0
  130. data/test/test_registry.rb +15 -0
  131. data/test/test_sensu.rb +11 -0
  132. data/test/test_slack.rb +57 -0
  133. data/test/test_socket.rb +34 -0
  134. data/test/test_statsd.rb +22 -0
  135. data/test/test_sugar.rb +42 -0
  136. data/test/test_system_portable_poller.rb +17 -0
  137. data/test/test_system_process.rb +30 -0
  138. data/test/test_task.rb +246 -0
  139. data/test/test_timeline.rb +37 -0
  140. data/test/test_trigger.rb +63 -0
  141. data/test/test_watch.rb +286 -0
  142. data/test/test_webhook.rb +22 -0
  143. metadata +475 -0
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/helper'
3
+
4
+ class TestProwl < Minitest::Test
5
+ def test_live_notify
6
+ prowl = God::Contacts::Prowl.new
7
+ prowl.name = "Prowly"
8
+ prowl.apikey = 'put_your_apikey_here'
9
+
10
+ Prowly.expects(:notify).returns(mock(:succeeded? => true))
11
+
12
+ prowl.notify("Test", Time.now, "Test", "Test", "")
13
+ assert_equal "sent prowl notification to #{prowl.name}", prowl.info
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestRegistry < Minitest::Test
4
+ def setup
5
+ God.registry.reset
6
+ end
7
+
8
+ def test_add
9
+ foo = God::Process.new
10
+ foo.name = 'foo'
11
+ God.registry.add(foo)
12
+ assert_equal 1, God.registry.size
13
+ assert_equal foo, God.registry['foo']
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSensu < Minitest::Test
4
+ def test_sensu_notify
5
+ sensu = God::Contacts::Sensu.new
6
+ sensu.check_name = "TestSensuContact"
7
+
8
+ UDPSocket.any_instance.expects(:send)
9
+ sensu.notify("Test", Time.now, "Test", "Test", "")
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSlack < Minitest::Test
4
+ def setup
5
+ @slack = God::Contacts::Slack.new
6
+
7
+ # new slack webhook url contains three random 'tokens' with length of 9, 9 and 24 characters
8
+ @slack.url = "https://hooks.slack.com/services/ABCABCABC/DEFDEFDEF/ABCDEFABCDEFABCDEFABCDEF"
9
+
10
+ @sample_data = {
11
+ :message => "a sample message",
12
+ :time => "2038-01-01 00:00:00",
13
+ :priority => "High",
14
+ :category => "Test",
15
+ :host => "example.com"
16
+ }
17
+ end
18
+
19
+ def test_api_url
20
+ assert_equal @slack.url, @slack.api_url.to_s
21
+ end
22
+
23
+ def test_notify
24
+ Net::HTTP.any_instance.expects(:request).returns(Net::HTTPSuccess.new('a', 'b', 'c'))
25
+
26
+ @slack.channel = "#ops"
27
+
28
+ @slack.notify('msg', Time.now, 'prio', 'cat', 'host')
29
+ assert_equal "successfully notified slack on channel #ops", @slack.info
30
+ end
31
+
32
+ def test_default_channel
33
+ Net::HTTP.any_instance.expects(:request).returns(Net::HTTPSuccess.new('a', 'b', 'c'))
34
+
35
+ @slack.notify('msg', Time.now, 'prio', 'cat', 'host')
36
+ assert_equal "successfully notified slack on channel #general", @slack.info
37
+ end
38
+
39
+ def test_default_formatting
40
+ text = @slack.text(@sample_data)
41
+ assert_equal "High alert on example.com: a sample message (Test, 2038-01-01 00:00:00)", text
42
+ end
43
+
44
+ def test_custom_formatting
45
+ @slack.format = "%{host}: %{message}"
46
+ text = @slack.text(@sample_data)
47
+ assert_equal "example.com: a sample message", text
48
+ end
49
+
50
+ def test_notify_channel
51
+ @slack.notify_channel = true
52
+ @slack.format = ""
53
+ text = @slack.text(@sample_data)
54
+ assert_equal "<!channel> ", text
55
+ end
56
+ end
57
+
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSocket < Minitest::Test
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
+ God::Socket.new
13
+ end
14
+
15
+ def test_should_use_supplied_port_and_host
16
+ DRb.expects(:start_service).with { |uri, object| uri == "drbunix:///tmp/god.9999.sock" && object.is_a?(God::Socket) }
17
+ server = God::Socket.new(9999)
18
+ end
19
+
20
+ def test_should_forward_foreign_method_calls_to_god
21
+ server = nil
22
+ server = God::Socket.new
23
+ God.expects(:send).with(:something_random)
24
+ server.something_random
25
+ end
26
+
27
+ # ping
28
+
29
+ def test_ping_should_return_true
30
+ server = nil
31
+ server = God::Socket.new
32
+ assert server.ping
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestStatsd < Minitest::Test
4
+ def setup
5
+ @statsd = God::Contacts::Statsd.new
6
+ end
7
+
8
+ def test_exists
9
+ God::Contacts::Statsd
10
+ end
11
+
12
+ def test_notify
13
+ [
14
+ 'cpu out of bounds',
15
+ 'memory out of bounds',
16
+ 'process is flapping'
17
+ ].each do |event_type|
18
+ ::Statsd.any_instance.expects(:increment).with("god.#{event_type.gsub(/\s/, '_')}.127_0_0_1.myapp-thin-1234")
19
+ @statsd.notify("myapp-thin-1234 [trigger] #{event_type}", Time.now, 'some priority', 'and some category', '127.0.0.1')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSugar < Minitest::Test
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 < Minitest::Test
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 < Minitest::Test
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
+
data/test/test_task.rb ADDED
@@ -0,0 +1,246 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTask < Minitest::Test
4
+ def setup
5
+ God.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
+ assert !@task.valid?
19
+ end
20
+
21
+ def test_valid_should_return_false_if_no_valid_states
22
+ @task.valid_states = nil
23
+ assert !@task.valid?
24
+ end
25
+
26
+ def test_valid_should_return_false_if_no_initial_state
27
+ @task.initial_state = nil
28
+ assert !@task.valid?
29
+ end
30
+
31
+ # transition
32
+
33
+ def test_transition_should_be_always_if_no_block_was_given
34
+ @task.transition(:foo, :bar)
35
+
36
+ assert_equal 5, @task.metrics.size
37
+ assert_equal Conditions::Always, @task.metrics[:foo].first.conditions.first.class
38
+ end
39
+
40
+ # method_missing
41
+
42
+ def test_method_missing_should_create_accessor_for_states
43
+ assert_nothing_raised do
44
+ @task.foo = 'testing'
45
+ end
46
+ end
47
+
48
+ def test_method_missing_should_raise_for_non_states
49
+ assert_raises NoMethodError do
50
+ @task.baz = 5
51
+ end
52
+ end
53
+
54
+ def test_method_missing_should_raise_for_non_setters
55
+ assert_raises NoMethodError do
56
+ @task.baz
57
+ end
58
+ end
59
+
60
+ # action
61
+
62
+ def test_action_should_send_string_commands_to_system
63
+ @task.foo = 'foo'
64
+ @task.driver.stubs(:in_driver_context?).returns(true)
65
+ @task.expects(:system).with('foo')
66
+ @task.action(:foo, nil)
67
+ end
68
+
69
+ def test_action_should_call_lambda_commands
70
+ @task.foo = lambda { }
71
+ @task.driver.stubs(:in_driver_context?).returns(true)
72
+ @task.foo.expects(:call)
73
+ @task.action(:foo, nil)
74
+ end
75
+
76
+ def test_action_should_raise_not_implemented_on_non_string_or_lambda_action
77
+ @task.driver.stubs(:in_driver_context?).returns(true)
78
+ assert_raises NotImplementedError do
79
+ @task.foo = 7
80
+ @task.action(:foo, nil)
81
+ end
82
+ end
83
+
84
+ def test_action_from_outside_driver_should_send_message_to_driver
85
+ @task.foo = 'foo'
86
+ @task.driver.expects(:message).with(:action, [:foo, nil])
87
+ @task.action(:foo, nil)
88
+ end
89
+
90
+ # attach
91
+
92
+ def test_attach_should_schedule_for_poll_condition
93
+ c = Conditions::FakePollCondition.new
94
+ @task.driver.expects(:schedule).with(c, 0)
95
+ @task.attach(c)
96
+ end
97
+
98
+ def test_attach_should_regsiter_for_event_condition
99
+ c = Conditions::FakeEventCondition.new
100
+ c.expects(:register)
101
+ @task.attach(c)
102
+ end
103
+
104
+ # detach
105
+
106
+ def test_detach_should_reset_poll_condition
107
+ c = Conditions::FakePollCondition.new
108
+ c.expects(:reset)
109
+ c.expects(:deregister).never
110
+ @task.detach(c)
111
+ end
112
+
113
+ def test_detach_should_deregister_event_conditions
114
+ c = Conditions::FakeEventCondition.new
115
+ c.expects(:deregister).once
116
+ @task.detach(c)
117
+ end
118
+
119
+ # trigger
120
+
121
+ def test_trigger_should_send_message_to_driver
122
+ c = Conditions::FakePollCondition.new
123
+ @task.driver.expects(:message).with(:handle_event, [c])
124
+ @task.trigger(c)
125
+ end
126
+
127
+ # handle_poll
128
+
129
+ def test_handle_poll_no_change_should_reschedule
130
+ c = Conditions::FakePollCondition.new
131
+ c.watch = @task
132
+ c.interval = 10
133
+
134
+ m = Metric.new(@task, {true => :up})
135
+ @task.directory[c] = m
136
+
137
+ c.expects(:test).returns(false)
138
+ @task.driver.expects(:schedule)
139
+ @task.handle_poll(c)
140
+ end
141
+
142
+ def test_handle_poll_change_should_move
143
+ c = Conditions::FakePollCondition.new
144
+ c.watch = @task
145
+ c.interval = 10
146
+
147
+ m = Metric.new(@task, {true => :up})
148
+ @task.directory[c] = m
149
+
150
+ c.expects(:test).returns(true)
151
+ @task.expects(:move).with(:up)
152
+ @task.handle_poll(c)
153
+ end
154
+
155
+ def test_handle_poll_should_use_overridden_transition
156
+ c = Conditions::Tries.new
157
+ c.watch = @task
158
+ c.times = 1
159
+ c.transition = :start
160
+ c.prepare
161
+
162
+ m = Metric.new(@task, {true => :up})
163
+ @task.directory[c] = m
164
+
165
+ @task.expects(:move).with(:start)
166
+ @task.handle_poll(c)
167
+ end
168
+
169
+ def test_handle_poll_should_notify_if_triggering
170
+ c = Conditions::FakePollCondition.new
171
+ c.watch = @task
172
+ c.interval = 10
173
+ c.notify = 'tom'
174
+
175
+ m = Metric.new(@task, {true => :up})
176
+ @task.directory[c] = m
177
+
178
+ c.expects(:test).returns(true)
179
+ @task.expects(:notify)
180
+ @task.handle_poll(c)
181
+ end
182
+
183
+ def test_handle_poll_should_not_notify_if_not_triggering
184
+ c = Conditions::FakePollCondition.new
185
+ c.watch = @task
186
+ c.interval = 10
187
+ c.notify = 'tom'
188
+
189
+ m = Metric.new(@task, {true => :up})
190
+ @task.directory[c] = m
191
+
192
+ c.expects(:test).returns(false)
193
+ @task.expects(:notify).never
194
+ @task.handle_poll(c)
195
+ end
196
+
197
+ def test_handle_poll_unexpected_exception_should_reschedule
198
+ c = Conditions::FakePollCondition.new
199
+ c.watch = @task
200
+ c.interval = 10
201
+
202
+ m = Metric.new(@task, {true => :up})
203
+ @task.directory[c] = m
204
+
205
+ c.expects(:test).raises(StandardError)
206
+ @task.driver.expects(:schedule)
207
+
208
+ @task.handle_poll(c)
209
+ end
210
+
211
+ # handle_event
212
+
213
+ def test_handle_event_should_move
214
+ c = Conditions::FakeEventCondition.new
215
+ c.watch = @task
216
+
217
+ m = Metric.new(@task, {true => :up})
218
+ @task.directory[c] = m
219
+
220
+ @task.expects(:move).with(:up)
221
+ @task.handle_event(c)
222
+ end
223
+
224
+ def test_handle_event_should_notify_if_triggering
225
+ c = Conditions::FakeEventCondition.new
226
+ c.watch = @task
227
+ c.notify = 'tom'
228
+
229
+ m = Metric.new(@task, {true => :up})
230
+ @task.directory[c] = m
231
+
232
+ @task.expects(:notify)
233
+ @task.handle_event(c)
234
+ end
235
+
236
+ def test_handle_event_should_not_notify_if_no_notify_set
237
+ c = Conditions::FakeEventCondition.new
238
+ c.watch = @task
239
+
240
+ m = Metric.new(@task, {true => :up})
241
+ @task.directory[c] = m
242
+
243
+ @task.expects(:notify).never
244
+ @task.handle_event(c)
245
+ end
246
+ end