dosire-god 0.7.9

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 (108) hide show
  1. data/History.txt +261 -0
  2. data/Manifest.txt +107 -0
  3. data/README.txt +59 -0
  4. data/Rakefile +35 -0
  5. data/bin/god +127 -0
  6. data/examples/events.god +84 -0
  7. data/examples/gravatar.god +54 -0
  8. data/examples/single.god +66 -0
  9. data/ext/god/extconf.rb +55 -0
  10. data/ext/god/kqueue_handler.c +123 -0
  11. data/ext/god/netlink_handler.c +167 -0
  12. data/init/god +42 -0
  13. data/lib/god/behavior.rb +52 -0
  14. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  15. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  16. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  17. data/lib/god/cli/command.rb +206 -0
  18. data/lib/god/cli/run.rb +177 -0
  19. data/lib/god/cli/version.rb +23 -0
  20. data/lib/god/condition.rb +96 -0
  21. data/lib/god/conditions/always.rb +23 -0
  22. data/lib/god/conditions/complex.rb +86 -0
  23. data/lib/god/conditions/cpu_usage.rb +80 -0
  24. data/lib/god/conditions/degrading_lambda.rb +52 -0
  25. data/lib/god/conditions/disk_usage.rb +27 -0
  26. data/lib/god/conditions/flapping.rb +128 -0
  27. data/lib/god/conditions/http_response_code.rb +168 -0
  28. data/lib/god/conditions/lambda.rb +25 -0
  29. data/lib/god/conditions/memory_usage.rb +82 -0
  30. data/lib/god/conditions/process_exits.rb +72 -0
  31. data/lib/god/conditions/process_running.rb +74 -0
  32. data/lib/god/conditions/tries.rb +44 -0
  33. data/lib/god/configurable.rb +57 -0
  34. data/lib/god/contact.rb +106 -0
  35. data/lib/god/contacts/email.rb +95 -0
  36. data/lib/god/dependency_graph.rb +41 -0
  37. data/lib/god/diagnostics.rb +37 -0
  38. data/lib/god/driver.rb +206 -0
  39. data/lib/god/errors.rb +24 -0
  40. data/lib/god/event_handler.rb +111 -0
  41. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  42. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  43. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  44. data/lib/god/logger.rb +120 -0
  45. data/lib/god/metric.rb +59 -0
  46. data/lib/god/process.rb +327 -0
  47. data/lib/god/registry.rb +32 -0
  48. data/lib/god/simple_logger.rb +53 -0
  49. data/lib/god/socket.rb +96 -0
  50. data/lib/god/sugar.rb +47 -0
  51. data/lib/god/system/portable_poller.rb +42 -0
  52. data/lib/god/system/process.rb +42 -0
  53. data/lib/god/system/slash_proc_poller.rb +82 -0
  54. data/lib/god/task.rb +487 -0
  55. data/lib/god/timeline.rb +25 -0
  56. data/lib/god/trigger.rb +43 -0
  57. data/lib/god/watch.rb +183 -0
  58. data/lib/god.rb +644 -0
  59. data/test/configs/child_events/child_events.god +44 -0
  60. data/test/configs/child_events/simple_server.rb +3 -0
  61. data/test/configs/child_polls/child_polls.god +37 -0
  62. data/test/configs/child_polls/simple_server.rb +12 -0
  63. data/test/configs/complex/complex.god +59 -0
  64. data/test/configs/complex/simple_server.rb +3 -0
  65. data/test/configs/contact/contact.god +74 -0
  66. data/test/configs/contact/simple_server.rb +3 -0
  67. data/test/configs/daemon_events/daemon_events.god +37 -0
  68. data/test/configs/daemon_events/simple_server.rb +8 -0
  69. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  70. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  71. data/test/configs/daemon_polls/simple_server.rb +6 -0
  72. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  73. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  74. data/test/configs/matias/matias.god +50 -0
  75. data/test/configs/real.rb +59 -0
  76. data/test/configs/running_load/running_load.god +16 -0
  77. data/test/configs/stress/simple_server.rb +3 -0
  78. data/test/configs/stress/stress.god +15 -0
  79. data/test/configs/task/logs/.placeholder +0 -0
  80. data/test/configs/task/task.god +26 -0
  81. data/test/configs/test.rb +61 -0
  82. data/test/helper.rb +151 -0
  83. data/test/suite.rb +6 -0
  84. data/test/test_behavior.rb +21 -0
  85. data/test/test_condition.rb +50 -0
  86. data/test/test_conditions_disk_usage.rb +56 -0
  87. data/test/test_conditions_http_response_code.rb +109 -0
  88. data/test/test_conditions_process_running.rb +44 -0
  89. data/test/test_conditions_tries.rb +67 -0
  90. data/test/test_contact.rb +109 -0
  91. data/test/test_dependency_graph.rb +62 -0
  92. data/test/test_driver.rb +11 -0
  93. data/test/test_event_handler.rb +80 -0
  94. data/test/test_god.rb +598 -0
  95. data/test/test_handlers_kqueue_handler.rb +16 -0
  96. data/test/test_logger.rb +63 -0
  97. data/test/test_metric.rb +72 -0
  98. data/test/test_process.rb +246 -0
  99. data/test/test_registry.rb +15 -0
  100. data/test/test_socket.rb +42 -0
  101. data/test/test_sugar.rb +42 -0
  102. data/test/test_system_portable_poller.rb +17 -0
  103. data/test/test_system_process.rb +30 -0
  104. data/test/test_task.rb +262 -0
  105. data/test/test_timeline.rb +37 -0
  106. data/test/test_trigger.rb +59 -0
  107. data/test/test_watch.rb +279 -0
  108. metadata +186 -0
data/test/test_task.rb ADDED
@@ -0,0 +1,262 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTask < Test::Unit::TestCase
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
+ 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
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTimeline < Test::Unit::TestCase
4
+ def setup
5
+ @timeline = Timeline.new(5)
6
+ end
7
+
8
+ def test_new_should_be_empty
9
+ assert_equal 0, @timeline.size
10
+ end
11
+
12
+ def test_should_not_grow_to_more_than_size
13
+ (1..10).each do |i|
14
+ @timeline.push(i)
15
+ end
16
+
17
+ assert_equal [6, 7, 8, 9, 10], @timeline
18
+ end
19
+
20
+ def test_clear_should_clear_array
21
+ @timeline << 1
22
+ assert_equal [1], @timeline
23
+ assert_equal [], @timeline.clear
24
+ end
25
+
26
+ # def test_benchmark
27
+ # require 'benchmark'
28
+ #
29
+ # count = 1_000_000
30
+ #
31
+ # t = Timeline.new(10)
32
+ #
33
+ # Benchmark.bmbm do |x|
34
+ # x.report("go") { count.times { t.push(5) } }
35
+ # end
36
+ # end
37
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTrigger < Test::Unit::TestCase
4
+ def setup
5
+ Trigger.reset
6
+ end
7
+
8
+ # base case
9
+
10
+ def test_should_have_empty_triggers
11
+ assert_equal({}, Trigger.triggers)
12
+ end
13
+
14
+ # register
15
+
16
+ def test_register_should_add_condition_to_triggers
17
+ c = Condition.new
18
+ c.watch = stub(:name => 'foo')
19
+ Trigger.register(c)
20
+
21
+ assert_equal({'foo' => [c]}, Trigger.triggers)
22
+ end
23
+
24
+ def test_register_should_add_condition_to_triggers_twice
25
+ watch = stub(:name => 'foo')
26
+ c = Condition.new
27
+ c.watch = watch
28
+ Trigger.register(c)
29
+
30
+ c2 = Condition.new
31
+ c2.watch = watch
32
+ Trigger.register(c2)
33
+
34
+ assert_equal({'foo' => [c, c2]}, Trigger.triggers)
35
+ end
36
+
37
+ # deregister
38
+
39
+ def test_deregister_should_remove_condition_from_triggers
40
+ c = Condition.new
41
+ c.watch = stub(:name => 'foo')
42
+ Trigger.register(c)
43
+ Trigger.deregister(c)
44
+
45
+ assert_equal({}, Trigger.triggers)
46
+ end
47
+
48
+ # broadcast
49
+
50
+ def test_broadcast_should_call_process_on_each_condition
51
+ c = Condition.new
52
+ c.watch = stub(:name => 'foo')
53
+ Trigger.register(c)
54
+
55
+ c.expects(:process).with(:state_change, [:up, :start])
56
+
57
+ Trigger.broadcast(c.watch, :state_change, [:up, :start])
58
+ end
59
+ end
@@ -0,0 +1,279 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestWatch < Test::Unit::TestCase
4
+ def setup
5
+ God.internal_init
6
+ @watch = Watch.new
7
+ @watch.name = 'foo'
8
+ @watch.start = lambda { }
9
+ @watch.stop = lambda { }
10
+ @watch.prepare
11
+ end
12
+
13
+ # new
14
+
15
+ def test_new_should_have_no_behaviors
16
+ assert_equal [], @watch.behaviors
17
+ end
18
+
19
+ def test_new_should_have_no_metrics
20
+ Watch::VALID_STATES.each do |state|
21
+ assert_equal [], @watch.metrics[state]
22
+ end
23
+ end
24
+
25
+ def test_new_should_have_standard_attributes
26
+ assert_nothing_raised do
27
+ @watch.name = 'foo'
28
+ @watch.start = 'start'
29
+ @watch.stop = 'stop'
30
+ @watch.restart = 'restart'
31
+ @watch.interval = 30
32
+ @watch.grace = 5
33
+ end
34
+ end
35
+
36
+ def test_new_should_have_unmonitored_state
37
+ assert_equal :unmonitored, @watch.state
38
+ end
39
+
40
+ # valid?
41
+
42
+ def test_valid?
43
+ God::Process.any_instance.expects(:valid?)
44
+ @watch.valid?
45
+ end
46
+
47
+ # behavior
48
+
49
+ def test_behavior_should_record_behavior
50
+ beh = nil
51
+ @watch.behavior(:fake_behavior) { |b| beh = b }
52
+ assert_equal 1, @watch.behaviors.size
53
+ assert_equal beh, @watch.behaviors.first
54
+ end
55
+
56
+ def test_invalid_behavior_should_abort
57
+ assert_abort do
58
+ @watch.behavior(:invalid)
59
+ end
60
+ end
61
+
62
+ # transition
63
+
64
+ def test_transition_should_abort_on_invalid_start_state
65
+ assert_abort do
66
+ @watch.transition(:foo, :bar)
67
+ end
68
+ end
69
+
70
+ def test_transition_should_accept_all_valid_start_states
71
+ assert_nothing_raised do
72
+ Watch::VALID_STATES.each do |state|
73
+ @watch.transition(state, :bar) { }
74
+ end
75
+ end
76
+ end
77
+
78
+ def test_transition_should_create_and_record_a_metric_for_the_given_start_state
79
+ @watch.transition(:init, :start) { }
80
+ assert_equal 1, @watch.metrics[:init].size
81
+ end
82
+
83
+ # lifecycle
84
+
85
+ def test_lifecycle_should_create_and_record_a_metric_for_nil_start_state
86
+ @watch.lifecycle { }
87
+ assert_equal 1, @watch.metrics[nil].size
88
+ end
89
+
90
+ # start_if
91
+
92
+ def test_start_if_should_place_a_metric_on_up_state
93
+ @watch.start_if { }
94
+ assert_equal 1, @watch.metrics[:up].size
95
+ end
96
+
97
+ # restart_if
98
+
99
+ def test_restart_if_should_place_a_metric_on_up_state
100
+ @watch.restart_if { }
101
+ assert_equal 1, @watch.metrics[:up].size
102
+ end
103
+
104
+ # monitor
105
+
106
+ def test_monitor_should_move_to_init_if_available
107
+ @watch.instance_eval do
108
+ transition(:init, :up) { }
109
+ end
110
+ @watch.expects(:move).with(:init)
111
+ @watch.monitor
112
+ end
113
+
114
+ def test_monitor_should_move_to_up_if_no_init_available
115
+ @watch.expects(:move).with(:up)
116
+ @watch.monitor
117
+ end
118
+
119
+ # unmonitor
120
+
121
+ def test_unmonitor_should_move_to_nil
122
+ @watch.expects(:move).with(:unmonitored)
123
+ @watch.unmonitor
124
+ end
125
+
126
+ # move
127
+
128
+ def test_move_should_not_clean_up_if_from_state_is_nil
129
+ Thread.current.stubs(:==).returns(true)
130
+ @watch.driver.expects(:message).never
131
+
132
+ metric = nil
133
+
134
+ @watch.instance_eval do
135
+ transition(:init, :up) do |on|
136
+ metric = on
137
+ on.condition(:process_running) do |c|
138
+ c.running = true
139
+ c.interval = 10
140
+ end
141
+ end
142
+ end
143
+
144
+ metric.expects(:disable).never
145
+
146
+ no_stdout { @watch.move(:init) }
147
+ end
148
+
149
+ def test_move_should_clean_up_from_state_if_not_nil
150
+ Thread.current.stubs(:==).returns(true)
151
+ @watch.driver.expects(:message).never
152
+
153
+ metric = nil
154
+
155
+ @watch.instance_eval do
156
+ transition(:init, :up) do |on|
157
+ metric = on
158
+ on.condition(:process_running) do |c|
159
+ c.running = true
160
+ c.interval = 10
161
+ end
162
+ end
163
+ end
164
+
165
+ no_stdout { @watch.move(:init) }
166
+
167
+ metric.expects(:disable)
168
+
169
+ no_stdout { @watch.move(:up) }
170
+ end
171
+
172
+ def test_move_should_call_action
173
+ Thread.current.stubs(:==).returns(true)
174
+ @watch.driver.expects(:message).never
175
+
176
+ @watch.expects(:action).with(:start)
177
+
178
+ no_stdout { @watch.move(:start) }
179
+ end
180
+
181
+ def test_move_should_move_to_up_state_if_no_start_or_restart_metric
182
+ Thread.current.stubs(:==).returns(true)
183
+ @watch.driver.expects(:message).never
184
+
185
+ [:start, :restart].each do |state|
186
+ @watch.expects(:action)
187
+ no_stdout { @watch.move(state) }
188
+ assert_equal :up, @watch.state
189
+ end
190
+ end
191
+
192
+ def test_move_should_enable_destination_metric
193
+ Thread.current.stubs(:==).returns(true)
194
+ @watch.driver.expects(:message).never
195
+
196
+ metric = nil
197
+
198
+ @watch.instance_eval do
199
+ transition(:init, :up) do |on|
200
+ metric = on
201
+ on.condition(:process_running) do |c|
202
+ c.running = true
203
+ c.interval = 10
204
+ end
205
+ end
206
+ end
207
+
208
+ metric.expects(:enable)
209
+
210
+ no_stdout { @watch.move(:init) }
211
+ end
212
+
213
+ # action
214
+
215
+ def test_action_should_pass_start_and_stop_actions_to_call_action
216
+ Thread.current.stubs(:==).returns(true)
217
+ @watch.driver.expects(:message).never
218
+
219
+ c = Conditions::FakePollCondition.new
220
+ [:start, :stop].each do |cmd|
221
+ @watch.expects(:call_action).with(c, cmd)
222
+ @watch.action(cmd, c)
223
+ end
224
+ end
225
+
226
+ def test_action_should_do_stop_then_start_if_no_restart_command
227
+ Thread.current.stubs(:==).returns(true)
228
+ @watch.driver.expects(:message).never
229
+
230
+ c = Conditions::FakePollCondition.new
231
+ @watch.expects(:call_action).with(c, :stop)
232
+ @watch.expects(:call_action).with(c, :start)
233
+ @watch.action(:restart, c)
234
+ end
235
+
236
+ def test_action_should_restart_to_call_action_if_present
237
+ Thread.current.stubs(:==).returns(true)
238
+ @watch.driver.expects(:message).never
239
+
240
+ @watch.restart = lambda { }
241
+ c = Conditions::FakePollCondition.new
242
+ @watch.expects(:call_action).with(c, :restart)
243
+ @watch.action(:restart, c)
244
+ end
245
+
246
+ # call_action
247
+
248
+ def test_call_action
249
+ c = Conditions::FakePollCondition.new
250
+ God::Process.any_instance.expects(:call_action).with(:start)
251
+ no_stdout { @watch.call_action(c, :start) }
252
+ end
253
+
254
+ def test_call_action_should_call_before_start_when_behavior_has_that
255
+ @watch.behavior(:fake_behavior)
256
+ c = Conditions::FakePollCondition.new
257
+ God::Process.any_instance.expects(:call_action).with(:start)
258
+ Behaviors::FakeBehavior.any_instance.expects(:before_start)
259
+ no_stdout { @watch.call_action(c, :start) }
260
+ end
261
+
262
+ def test_call_action_should_call_after_start_when_behavior_has_that
263
+ @watch.behavior(:fake_behavior)
264
+ c = Conditions::FakePollCondition.new
265
+ God::Process.any_instance.expects(:call_action).with(:start)
266
+ Behaviors::FakeBehavior.any_instance.expects(:after_start)
267
+ no_stdout { @watch.call_action(c, :start) }
268
+ end
269
+
270
+ # canonical_hash_form
271
+
272
+ def test_canonical_hash_form_should_convert_symbol_to_hash
273
+ assert_equal({true => :foo}, @watch.canonical_hash_form(:foo))
274
+ end
275
+
276
+ def test_canonical_hash_form_should_convert_hash_to_hash
277
+ assert_equal({true => :foo}, @watch.canonical_hash_form(true => :foo))
278
+ end
279
+ end