eye 0.1.11

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 (190) hide show
  1. data/.gitignore +31 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +132 -0
  6. data/Rakefile +18 -0
  7. data/bin/eye +282 -0
  8. data/bin/loader_eye +56 -0
  9. data/examples/processes/em.rb +56 -0
  10. data/examples/processes/forking.rb +20 -0
  11. data/examples/processes/sample.rb +144 -0
  12. data/examples/rbenv.eye +11 -0
  13. data/examples/test.eye +65 -0
  14. data/examples/unicorn.eye +29 -0
  15. data/eye.gemspec +37 -0
  16. data/lib/eye.rb +25 -0
  17. data/lib/eye/application.rb +65 -0
  18. data/lib/eye/checker.rb +118 -0
  19. data/lib/eye/checker/cpu.rb +27 -0
  20. data/lib/eye/checker/file_ctime.rb +29 -0
  21. data/lib/eye/checker/file_size.rb +38 -0
  22. data/lib/eye/checker/http.rb +94 -0
  23. data/lib/eye/checker/memory.rb +27 -0
  24. data/lib/eye/checker/socket.rb +148 -0
  25. data/lib/eye/checker/validation.rb +49 -0
  26. data/lib/eye/child_process.rb +75 -0
  27. data/lib/eye/client.rb +32 -0
  28. data/lib/eye/control.rb +2 -0
  29. data/lib/eye/controller.rb +43 -0
  30. data/lib/eye/controller/commands.rb +64 -0
  31. data/lib/eye/controller/helpers.rb +61 -0
  32. data/lib/eye/controller/load.rb +224 -0
  33. data/lib/eye/controller/send_command.rb +88 -0
  34. data/lib/eye/controller/status.rb +136 -0
  35. data/lib/eye/dsl.rb +52 -0
  36. data/lib/eye/dsl/application_opts.rb +33 -0
  37. data/lib/eye/dsl/chain.rb +12 -0
  38. data/lib/eye/dsl/child_process_opts.rb +7 -0
  39. data/lib/eye/dsl/config_opts.rb +11 -0
  40. data/lib/eye/dsl/group_opts.rb +27 -0
  41. data/lib/eye/dsl/helpers.rb +12 -0
  42. data/lib/eye/dsl/main.rb +58 -0
  43. data/lib/eye/dsl/opts.rb +88 -0
  44. data/lib/eye/dsl/process_opts.rb +21 -0
  45. data/lib/eye/dsl/pure_opts.rb +132 -0
  46. data/lib/eye/dsl/validate.rb +41 -0
  47. data/lib/eye/group.rb +125 -0
  48. data/lib/eye/group/chain.rb +68 -0
  49. data/lib/eye/io/unix_server.rb +44 -0
  50. data/lib/eye/io/unix_socket.rb +39 -0
  51. data/lib/eye/loader.rb +13 -0
  52. data/lib/eye/logger.rb +80 -0
  53. data/lib/eye/process.rb +83 -0
  54. data/lib/eye/process/child.rb +61 -0
  55. data/lib/eye/process/commands.rb +256 -0
  56. data/lib/eye/process/config.rb +70 -0
  57. data/lib/eye/process/controller.rb +72 -0
  58. data/lib/eye/process/data.rb +46 -0
  59. data/lib/eye/process/monitor.rb +97 -0
  60. data/lib/eye/process/notify.rb +17 -0
  61. data/lib/eye/process/scheduler.rb +50 -0
  62. data/lib/eye/process/states.rb +92 -0
  63. data/lib/eye/process/states_history.rb +62 -0
  64. data/lib/eye/process/system.rb +60 -0
  65. data/lib/eye/process/trigger.rb +32 -0
  66. data/lib/eye/process/watchers.rb +67 -0
  67. data/lib/eye/server.rb +51 -0
  68. data/lib/eye/settings.rb +35 -0
  69. data/lib/eye/system.rb +145 -0
  70. data/lib/eye/system_resources.rb +83 -0
  71. data/lib/eye/trigger.rb +53 -0
  72. data/lib/eye/trigger/flapping.rb +24 -0
  73. data/lib/eye/utils.rb +5 -0
  74. data/lib/eye/utils/alive_array.rb +31 -0
  75. data/lib/eye/utils/celluloid_chain.rb +51 -0
  76. data/lib/eye/utils/leak_19.rb +7 -0
  77. data/lib/eye/utils/tail.rb +20 -0
  78. data/spec/checker/cpu_spec.rb +58 -0
  79. data/spec/checker/file_ctime_spec.rb +34 -0
  80. data/spec/checker/file_size_spec.rb +107 -0
  81. data/spec/checker/http_spec.rb +109 -0
  82. data/spec/checker/memory_spec.rb +64 -0
  83. data/spec/checker/socket_spec.rb +116 -0
  84. data/spec/checker_spec.rb +188 -0
  85. data/spec/child_process/child_process_spec.rb +46 -0
  86. data/spec/client_server_spec.rb +34 -0
  87. data/spec/controller/commands_spec.rb +92 -0
  88. data/spec/controller/controller_spec.rb +133 -0
  89. data/spec/controller/find_objects_spec.rb +150 -0
  90. data/spec/controller/group_spec.rb +110 -0
  91. data/spec/controller/intergration_spec.rb +327 -0
  92. data/spec/controller/load_spec.rb +326 -0
  93. data/spec/controller/races_spec.rb +70 -0
  94. data/spec/controller/stop_on_delete_spec.rb +157 -0
  95. data/spec/dsl/chain_spec.rb +140 -0
  96. data/spec/dsl/checks_spec.rb +202 -0
  97. data/spec/dsl/config_spec.rb +44 -0
  98. data/spec/dsl/dsl_spec.rb +73 -0
  99. data/spec/dsl/getter_spec.rb +223 -0
  100. data/spec/dsl/integration_spec.rb +311 -0
  101. data/spec/dsl/load_spec.rb +52 -0
  102. data/spec/dsl/process_spec.rb +330 -0
  103. data/spec/dsl/sub_procs_spec.rb +93 -0
  104. data/spec/dsl/with_server_spec.rb +104 -0
  105. data/spec/example/em.rb +57 -0
  106. data/spec/example/forking.rb +20 -0
  107. data/spec/example/sample.rb +154 -0
  108. data/spec/fixtures/dsl/0.rb +8 -0
  109. data/spec/fixtures/dsl/0a.rb +8 -0
  110. data/spec/fixtures/dsl/0c.rb +8 -0
  111. data/spec/fixtures/dsl/1.rb +5 -0
  112. data/spec/fixtures/dsl/bad.eye +6 -0
  113. data/spec/fixtures/dsl/configs/1.eye +3 -0
  114. data/spec/fixtures/dsl/configs/2.eye +1 -0
  115. data/spec/fixtures/dsl/configs/3.eye +1 -0
  116. data/spec/fixtures/dsl/configs/4.eye +3 -0
  117. data/spec/fixtures/dsl/empty.eye +20 -0
  118. data/spec/fixtures/dsl/include_test.eye +5 -0
  119. data/spec/fixtures/dsl/include_test/1.rb +6 -0
  120. data/spec/fixtures/dsl/include_test/ha.rb +4 -0
  121. data/spec/fixtures/dsl/include_test2.eye +5 -0
  122. data/spec/fixtures/dsl/integration.eye +30 -0
  123. data/spec/fixtures/dsl/integration2.eye +32 -0
  124. data/spec/fixtures/dsl/integration_locks.eye +30 -0
  125. data/spec/fixtures/dsl/integration_sor.eye +32 -0
  126. data/spec/fixtures/dsl/integration_sor2.eye +27 -0
  127. data/spec/fixtures/dsl/integration_sor3.eye +32 -0
  128. data/spec/fixtures/dsl/load.eye +25 -0
  129. data/spec/fixtures/dsl/load2.eye +7 -0
  130. data/spec/fixtures/dsl/load2_dup2.eye +13 -0
  131. data/spec/fixtures/dsl/load2_dup_pid.eye +7 -0
  132. data/spec/fixtures/dsl/load3.eye +10 -0
  133. data/spec/fixtures/dsl/load4.eye +7 -0
  134. data/spec/fixtures/dsl/load5.eye +8 -0
  135. data/spec/fixtures/dsl/load6.eye +17 -0
  136. data/spec/fixtures/dsl/load_dubls.eye +36 -0
  137. data/spec/fixtures/dsl/load_dup_ex_names.eye +15 -0
  138. data/spec/fixtures/dsl/load_error.eye +5 -0
  139. data/spec/fixtures/dsl/load_error_folder/load3.eye +10 -0
  140. data/spec/fixtures/dsl/load_error_folder/load4.eye +7 -0
  141. data/spec/fixtures/dsl/load_folder/load3.eye +10 -0
  142. data/spec/fixtures/dsl/load_folder/load4.eye +7 -0
  143. data/spec/fixtures/dsl/load_int.eye +8 -0
  144. data/spec/fixtures/dsl/load_int2.eye +13 -0
  145. data/spec/fixtures/dsl/load_logger.eye +26 -0
  146. data/spec/fixtures/dsl/load_logger2.eye +3 -0
  147. data/spec/fixtures/dsl/long_load.eye +5 -0
  148. data/spec/fixtures/dsl/subfolder1/proc1.rb +3 -0
  149. data/spec/fixtures/dsl/subfolder2.eye +9 -0
  150. data/spec/fixtures/dsl/subfolder2/common.rb +1 -0
  151. data/spec/fixtures/dsl/subfolder2/proc2.rb +3 -0
  152. data/spec/fixtures/dsl/subfolder2/sub/proc3.rb +6 -0
  153. data/spec/fixtures/dsl/subfolder3.eye +8 -0
  154. data/spec/fixtures/dsl/subfolder3/common.rb +1 -0
  155. data/spec/fixtures/dsl/subfolder3/proc4.rb +3 -0
  156. data/spec/fixtures/dsl/subfolder3/sub/proc5.rb +6 -0
  157. data/spec/fixtures/dsl/subfolder4.eye +6 -0
  158. data/spec/fixtures/dsl/subfolder4/a.rb +2 -0
  159. data/spec/fixtures/dsl/subfolder4/b.rb +1 -0
  160. data/spec/fixtures/dsl/subfolder4/c.rb +1 -0
  161. data/spec/mock_spec.rb +32 -0
  162. data/spec/process/checks/child_checks_spec.rb +79 -0
  163. data/spec/process/checks/cpu_spec.rb +114 -0
  164. data/spec/process/checks/ctime_spec.rb +43 -0
  165. data/spec/process/checks/fsize_spec.rb +22 -0
  166. data/spec/process/checks/http_spec.rb +52 -0
  167. data/spec/process/checks/intergration_spec.rb +32 -0
  168. data/spec/process/checks/memory_spec.rb +113 -0
  169. data/spec/process/child_process_spec.rb +125 -0
  170. data/spec/process/config_spec.rb +75 -0
  171. data/spec/process/controller_spec.rb +173 -0
  172. data/spec/process/monitoring_spec.rb +180 -0
  173. data/spec/process/restart_spec.rb +174 -0
  174. data/spec/process/scheduler_spec.rb +150 -0
  175. data/spec/process/start_spec.rb +261 -0
  176. data/spec/process/states_history_spec.rb +118 -0
  177. data/spec/process/stop_spec.rb +150 -0
  178. data/spec/process/system_spec.rb +100 -0
  179. data/spec/process/triggers/flapping_spec.rb +81 -0
  180. data/spec/process/update_config_spec.rb +63 -0
  181. data/spec/spec_helper.rb +120 -0
  182. data/spec/support/rr_celluloid.rb +36 -0
  183. data/spec/support/scheduler_hack.rb +16 -0
  184. data/spec/support/spec_support.rb +164 -0
  185. data/spec/system_resources_spec.rb +59 -0
  186. data/spec/system_spec.rb +170 -0
  187. data/spec/utils/alive_array_spec.rb +50 -0
  188. data/spec/utils/celluloid_chain_spec.rb +82 -0
  189. data/spec/utils/tail_spec.rb +21 -0
  190. metadata +558 -0
@@ -0,0 +1,261 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "Process Start" do
4
+
5
+ it "process already runned, started new process" do
6
+ # something already started process
7
+ @pid = Eye::System.daemonize(C.p1[:start_command], C.p1)[:pid]
8
+ Eye::System.pid_alive?(@pid).should == true
9
+ File.open(C.p1[:pid_file], 'w'){|f| f.write(@pid) }
10
+
11
+ # should not try to start something
12
+ dont_allow(Eye::System).daemonize
13
+ dont_allow(Eye::System).execute
14
+
15
+ # when start process
16
+ @process = process C.p1
17
+ @process.start.should == :ok
18
+
19
+ # wait while monitoring completely started
20
+ sleep 0.5
21
+
22
+ # pid and should be ok
23
+ @process.pid.should == @pid
24
+ @process.load_pid_from_file.should == @pid
25
+
26
+ @process.state_name.should == :up
27
+ @process.watchers.keys.should == [:check_alive]
28
+ end
29
+
30
+ it "process started and up, receive command start" do
31
+ @process = process C.p1
32
+ @process.start.should == {:pid=>@process.pid}
33
+ sleep 0.5
34
+ @process.state_name.should == :up
35
+ @process.watchers.keys.should == [:check_alive]
36
+
37
+ @process.start.should == :ok
38
+ sleep 1
39
+ @process.state_name.should == :up
40
+ @process.watchers.keys.should == [:check_alive]
41
+ end
42
+
43
+ [C.p1, C.p2].each do |c|
44
+ it "start new process, with config #{c[:name]}" do
45
+ @process = process c
46
+ @process.start.should == {:pid=>@process.pid}
47
+
48
+ sleep 0.5
49
+
50
+ @pid = @process.pid
51
+ @process.load_pid_from_file.should == @pid
52
+
53
+ @process.state_name.should == :up
54
+ @process.watchers.keys.should == [:check_alive]
55
+ end
56
+
57
+ it "pid_file already exists, but process not, with config #{c[:name]}" do
58
+ File.open(C.p1[:pid_file], 'w'){|f| f.write(1234567) }
59
+
60
+ @process = process c
61
+ @process.start.should == {:pid=>@process.pid}
62
+
63
+ sleep 0.5
64
+
65
+ @pid = @process.pid
66
+ @pid.should_not == 1234567
67
+ @process.load_pid_from_file.should == @pid
68
+
69
+ @process.state_name.should == :up
70
+ end
71
+
72
+ it "process crushed, with config #{c[:name]}" do
73
+ @process = process(c.merge(:start_command => c[:start_command] + " -r" ))
74
+ @process.start.should == {:error=>:not_realy_running}
75
+
76
+ sleep 1
77
+
78
+ # may be not saving pid?
79
+ #@pid = @process.pid
80
+ #@pid.should > 0
81
+ #@process.load_pid_from_file.should == @pid
82
+
83
+ # should try to up process many times
84
+ @process.states_history.seq?(:unmonitored, :starting, :down, :starting).should == true
85
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
86
+
87
+ @process.watchers.keys.should == []
88
+ end
89
+
90
+ it "start with invalid command" do
91
+ @process = process(c.merge(:start_command => "asdf asdf1 r f324 f324f 32f44f"))
92
+ mock(@process).check_crush
93
+ res = @process.start
94
+ res.should == {:error=>"#<Errno::ENOENT: No such file or directory - asdf>"}
95
+
96
+ sleep 0.5
97
+
98
+ @process.pid.should == nil
99
+ @process.load_pid_from_file.should == nil
100
+ [:starting, :down].should include(@process.state_name)
101
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
102
+ end
103
+
104
+ it "start PROBLEM with stdout permissions" do
105
+ @process = process(c.merge(:stdout => "/var/run/1.log"))
106
+ mock(@process).check_crush
107
+ res = @process.start
108
+ res.should == {:error=>"#<Errno::EACCES: Permission denied - open>"}
109
+
110
+ sleep 0.5
111
+
112
+ @process.pid.should == nil
113
+ @process.load_pid_from_file.should == nil
114
+ [:starting, :down].should include(@process.state_name)
115
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
116
+ end
117
+
118
+ it "start PROBLEM binary permissions" do
119
+ @process = process(c.merge(:start_command => "./sample.rb"))
120
+ mock(@process).check_crush
121
+ res = @process.start
122
+ res.should == {:error=>"#<Errno::EACCES: Permission denied - ./sample.rb>"}
123
+
124
+ sleep 0.5
125
+
126
+ @process.pid.should == nil
127
+ @process.load_pid_from_file.should == nil
128
+ [:starting, :down].should include(@process.state_name)
129
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
130
+ end
131
+
132
+ end
133
+
134
+ it "C.p1 pid_file failed to write" do
135
+ @process = process(C.p1.merge(:pid_file => "/tmpasdfasdf/asdfa/dfa/df/ad/fad/fd.pid"))
136
+ res = @process.start
137
+ res.should == {:error=>:cant_write_pid}
138
+
139
+ sleep 1
140
+
141
+ [:starting, :down].should include(@process.state_name)
142
+ @process.states_history.seq?(:unmonitored, :starting, :down, :starting).should == true
143
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
144
+
145
+ @process.watchers.keys.should == []
146
+ end
147
+
148
+ it "C.p2 pid_file failed to write" do
149
+ pid = "/tmpasdfasdf/asdfa/dfa/df/ad/fad/fd.pid"
150
+ @process = process(C.p2.merge(:pid_file => pid,
151
+ :start_command => "ruby sample.rb -d --pid #{pid} --log #{C.log_name}"))
152
+ res = @process.start
153
+ res.should == {:error=>:pid_not_found}
154
+
155
+ sleep 1
156
+
157
+ [:starting, :down].should include(@process.state_name)
158
+ @process.states_history.seq?(:unmonitored, :starting, :down, :starting).should == true
159
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
160
+
161
+ @process.watchers.keys.should == []
162
+ end
163
+
164
+ it "long process with #{C.p1[:name]} (with daemonize)" do
165
+ # this is no matter for starting
166
+ @process = process(C.p1.merge(:start_command => C.p1[:start_command] + " --daemonize_delay 3",
167
+ :start_grace => 2.seconds ))
168
+ @process.start.should == {:pid=>@process.pid}
169
+
170
+ sleep 5
171
+ Eye::System.pid_alive?(@process.pid).should == true
172
+ @process.state_name.should == :up
173
+ end
174
+
175
+ it "long process with #{C.p2[:name]}" do
176
+ @process = process(C.p2.merge(:start_command => C.p2[:start_command] + " --daemonize_delay 3",
177
+ :start_timeout => 2.seconds))
178
+ @process.start.should == {:error=>"#<Timeout::Error: execution expired>"}
179
+
180
+ sleep 0.5
181
+ @process.pid.should == nil
182
+ @process.load_pid_from_file.should == nil
183
+
184
+ [:starting, :down].should include(@process.state_name)
185
+
186
+ @process.states_history.seq?(:unmonitored, :starting, :down, :starting).should == true
187
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
188
+ end
189
+
190
+ it "long process with #{C.p2[:name]} but start_timeout is OK" do
191
+ @process = process(C.p2.merge(:start_command => C.p2[:start_command] + " --daemonize_delay 3",
192
+ :start_timeout => 10.seconds))
193
+ @process.start.should == {:pid => @process.pid}
194
+
195
+ @process.load_pid_from_file.should == @process.pid
196
+ @process.state_name.should == :up
197
+ end
198
+
199
+ # O_o, what checks this spec
200
+ it "blocking start with lock" do
201
+ @process = process(C.p2.merge(:start_command => C.p2[:start_command] + " --daemonize_delay 3 -L 1.lock", :start_timeout => 2.seconds))
202
+ @process.start.should == {:error => "#<Timeout::Error: execution expired>"}
203
+
204
+ sleep 0.5
205
+ @process.pid.should == nil
206
+ @process.load_pid_from_file.should == nil
207
+
208
+ [:starting, :down].should include(@process.state_name)
209
+
210
+ @process.states_history.seq?(:unmonitored, :starting, :down, :starting).should == true
211
+ @process.states_history.all?(:unmonitored, :starting, :down).should == true
212
+ end
213
+
214
+ it "bad config daemonize self daemonized process pid the same" do
215
+ # little crazy behaviour, but process after first death, upped from pid_file pid
216
+ # NOT RECOMENDED FOR USE CASE
217
+ @process = process(C.p2.merge(:daemonize => true, :start_grace => 10.seconds))
218
+ old_pid = @process.pid
219
+
220
+ @process.start.should == {:error => :not_realy_running}
221
+
222
+ sleep 5
223
+
224
+ # should reload process from pid_file
225
+ @process.state_name.should == :up
226
+ @process.pid.should_not == old_pid
227
+ @process.load_pid_from_file.should == @process.pid
228
+ end
229
+
230
+ it "bad config daemonize self daemonized process pid different" do
231
+ # NOT RECOMENDED FOR USE CASE
232
+ @process = process(C.p2.merge(:daemonize => true, :pid_file => "2.pid", :start_grace => 10.seconds))
233
+ @process.start.should == {:error => :not_realy_running}
234
+ @process.pid.should == nil
235
+
236
+ ensure_kill_samples
237
+ end
238
+
239
+ it "without start command" do
240
+ @process = process(C.p2.merge(:start_command => nil))
241
+ @process.start.should == :no_start_command
242
+ sleep 1
243
+ @process.unmonitored?.should == true
244
+ end
245
+
246
+ [:up, :starting, :stopping, :restarting].each do |st|
247
+ it "should not start from #{st}" do
248
+ @process = process(C.p1)
249
+ @process.state = st.to_s # force set state
250
+
251
+ dont_allow(Eye::System).daemonize
252
+ dont_allow(Eye::System).execute
253
+
254
+ @process.start.should == :state_error
255
+ @process.state_name.should == st
256
+
257
+ @process.pid.should == nil
258
+ end
259
+ end
260
+
261
+ end
@@ -0,0 +1,118 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ describe "Eye::Process::StatesHistory" do
5
+ before :each do
6
+ @h = Eye::Process::StatesHistory.new
7
+ end
8
+
9
+ it "should work" do
10
+ @h << :up
11
+ @h.push :down, 'bla'
12
+
13
+ @h.states.should == [:up, :down]
14
+ @h.last_state.should == :down
15
+ @h.last_state_changed_at.should be_within(2.seconds).of(Time.now)
16
+ @h.last[:reason].should == 'bla'
17
+ end
18
+
19
+ it "states for period" do
20
+ @h.push :up, nil, 5.minutes.ago
21
+ @h.push :down, nil, 4.minutes.ago
22
+ @h.push :start, nil, 3.minutes.ago
23
+ @h.push :stop, nil, 2.minutes.ago
24
+ @h.push :up, nil, 1.minutes.ago
25
+ @h.push :down, nil, 0.minutes.ago
26
+
27
+ @h.states_for_period(1.5.minutes).should == [:up, :down]
28
+ @h.states_for_period(2.5.minutes).should == [:stop, :up, :down]
29
+ @h.states_for_period(6.minutes).should == [:up, :down, :start, :stop, :up, :down]
30
+ end
31
+
32
+ it "seq?" do
33
+ @h << :unmonitored
34
+ @h << :starting
35
+ @h << :down
36
+ @h << :starting
37
+
38
+ @h.seq?([:starting, :down, :starting]).should == true
39
+ @h.seq?(:starting, :down, :starting).should == true
40
+ @h.seq?([:starting, :down]).should == true
41
+
42
+ @h.seq?([:starting, :up]).should == false
43
+ @h.seq?([:starting, :starting]).should == false
44
+ @h.seq?(:starting, :starting).should == false
45
+
46
+ @h.seq?(:down).should == true
47
+ @h.seq?(:up).should == false
48
+ end
49
+
50
+ it "any?" do
51
+ @h << :unmonitored
52
+ @h << :starting
53
+ @h << :down
54
+ @h << :starting
55
+
56
+ @h.any?([:starting, :down, :starting]).should == true
57
+ @h.any?(:starting, :down, :starting).should == true
58
+ @h.any?(:up).should == false
59
+ @h.any?(:up, :stopping).should == false
60
+ @h.any?(:up, :down).should == true
61
+ @h.any?(:down).should == true
62
+ end
63
+
64
+ it "noone?" do
65
+ @h << :unmonitored
66
+ @h << :starting
67
+ @h << :down
68
+ @h << :starting
69
+
70
+ @h.noone?(:up, :stopping).should == true
71
+ @h.noone?(:up, :down).should == true
72
+ end
73
+
74
+ it "end?" do
75
+ @h << :unmonitored
76
+ @h << :starting
77
+ @h << :down
78
+ @h << :starting
79
+
80
+ @h.end?(:down, :starting).should == true
81
+ @h.end?(:starting, :down).should == false
82
+
83
+ @h.end?(:starting).should == true
84
+ @h.end?(:down).should == false
85
+
86
+ @h.end?(:starting, :down, :starting).should == true
87
+ @h.end?(:unmonitored, :starting, :down, :starting).should == true
88
+ end
89
+
90
+ it "all?" do
91
+ @h << :unmonitored
92
+ @h << :starting
93
+ @h << :down
94
+ @h << :starting
95
+
96
+ @h.all?([:starting, :down, :starting]).should == false
97
+ @h.all?(:starting, :down, :starting).should == false
98
+ @h.all?(:starting, :down, :starting, :unmonitored).should == true
99
+ @h.all?(:down, :starting, :unmonitored).should == true
100
+
101
+ @h.all?(:up).should == false
102
+ @h.all?(:up, :stopping).should == false
103
+ @h.all?(:up, :down).should == false
104
+ @h.all?(:down).should == false
105
+ end
106
+
107
+ it "state_count" do
108
+ @h << :unmonitored
109
+ @h << :starting
110
+ @h << :down
111
+ @h << :starting
112
+
113
+ @h.state_count(:down).should == 1
114
+ @h.state_count(:starting).should == 2
115
+ @h.state_count(:up).should == 0
116
+ end
117
+
118
+ end
@@ -0,0 +1,150 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "Process Stop" do
4
+
5
+ describe "clear_pid_file" do
6
+ it "stop should clear pid by default for daemonize" do
7
+ start_ok_process(C.p1)
8
+
9
+ @process.stop_process
10
+
11
+ Eye::System.pid_alive?(@pid).should == false
12
+ @process.state_name.should == :down
13
+
14
+ @process.load_pid_from_file.should == nil
15
+ end
16
+
17
+ it "stop should not clear pid by default for not daemonize" do
18
+ start_ok_process(C.p2)
19
+
20
+ @process.stop_process
21
+
22
+ Eye::System.pid_alive?(@pid).should == false
23
+ @process.state_name.should == :down
24
+
25
+ @process.load_pid_from_file.should == @pid
26
+ end
27
+
28
+ it "for not daemonize, but option enabled by manual" do
29
+ start_ok_process(C.p2.merge(:control_pid => true))
30
+
31
+ @process.stop_process
32
+
33
+ Eye::System.pid_alive?(@pid).should == false
34
+ @process.state_name.should == :down
35
+
36
+ @process.load_pid_from_file.should == nil
37
+ end
38
+ end
39
+
40
+ it "stop process by default command" do
41
+ start_ok_process
42
+
43
+ dont_allow(@process).check_crush
44
+ @process.stop_process
45
+
46
+ Eye::System.pid_alive?(@pid).should == false
47
+ @process.pid.should == @pid
48
+ @process.state_name.should == :down
49
+ @process.states_history.end?(:up, :stopping, :down).should == true
50
+ @process.watchers.keys.should == []
51
+ end
52
+
53
+ it "stop process by default command, and its not die by TERM, should stop anyway" do
54
+ start_ok_process(C.p2.merge(:start_command => C.p2[:start_command] + " -T"))
55
+ Eye::System.pid_alive?(@pid).should == true
56
+
57
+ dont_allow(@process).check_crush
58
+ @process.stop_process
59
+
60
+ Eye::System.pid_alive?(@pid).should == false
61
+ @process.pid.should == @pid
62
+ @process.state_name.should == :down
63
+ @process.states_history.end?(:up, :stopping, :down).should == true
64
+ @process.watchers.keys.should == []
65
+ end
66
+
67
+ it "stop process by specific command" do
68
+ start_ok_process(C.p1.merge(:stop_command => "kill -9 {{PID}}"))
69
+
70
+ dont_allow(@process).check_crush
71
+ @process.stop_process
72
+
73
+ Eye::System.pid_alive?(@pid).should == false
74
+ @process.state_name.should == :down
75
+ end
76
+
77
+ it "bad command" do
78
+ start_ok_process(C.p1.merge(:stop_command => "kill -0 {{PID}}"))
79
+
80
+ @process.stop_process
81
+
82
+ Eye::System.pid_alive?(@pid).should == true
83
+ @process.state_name.should == :unmonitored # cant stop with this command, so :unmonitored
84
+ end
85
+
86
+ it "watch_file" do
87
+ wf = File.join(C.p1[:working_dir], %w{1111.stop})
88
+ start_ok_process(C.p1.merge(:stop_command => "touch #{wf}",
89
+ :start_command => C.p1[:start_command] + " -w #{wf}"))
90
+
91
+ @process.stop_process
92
+
93
+ Eye::System.pid_alive?(@pid).should == false
94
+ @process.state_name.should == :down
95
+
96
+ File.exists?(wf).should == false
97
+
98
+ data = File.read(@log)
99
+ data.should include("watch file finded")
100
+ end
101
+
102
+ it "stop process by stop_signals" do
103
+ start_ok_process(C.p1.merge(:stop_signals => [9, 2.seconds]))
104
+
105
+ @process.stop_process!
106
+ sleep 1
107
+ Eye::System.pid_alive?(@pid).should == false
108
+ end
109
+
110
+ it "stop process by stop_signals" do
111
+ start_ok_process(C.p1.merge(:stop_signals => ['usr1', 3.seconds, :TERM, 2.seconds]))
112
+
113
+ @process.stop_process!
114
+ sleep 1.5
115
+ Eye::System.pid_alive?(@pid).should == true
116
+ sleep 1.5
117
+ Eye::System.pid_alive?(@pid).should == true
118
+ sleep 1
119
+ Eye::System.pid_alive?(@pid).should == false
120
+
121
+ # should capture log
122
+ data = File.read(@log)
123
+ data.should include("USR1 signal")
124
+ end
125
+
126
+ it "long stop" do
127
+ start_ok_process(C.p3)
128
+ pid = @process.pid
129
+
130
+ @process.stop_process
131
+ @process.state_name.should == :down
132
+
133
+ Eye::System.pid_alive?(pid).should == false
134
+ end
135
+
136
+ it "stop process by stop_signals and commands"
137
+
138
+ [:unmonitored, :down, :starting, :stopping].each do |st|
139
+ it "no stop from #{st}" do
140
+ @process = process(C.p1)
141
+ @process.state = st.to_s # force set state
142
+
143
+ dont_allow(@process).kill_process
144
+
145
+ @process.stop_process
146
+ @process.state_name.should == st
147
+ end
148
+ end
149
+
150
+ end