sanford 0.17.0 → 0.18.0
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bench/report.rb +2 -0
- data/bench/report.txt +28 -37
- data/lib/sanford/connection_handler.rb +10 -3
- data/lib/sanford/error_handler.rb +4 -4
- data/lib/sanford/io_pipe.rb +40 -0
- data/lib/sanford/process.rb +108 -28
- data/lib/sanford/router.rb +5 -0
- data/lib/sanford/server.rb +133 -95
- data/lib/sanford/server_data.rb +27 -28
- data/lib/sanford/template_source.rb +2 -2
- data/lib/sanford/version.rb +1 -1
- data/sanford.gemspec +4 -5
- data/test/helper.rb +11 -0
- data/test/support/app_server.rb +6 -3
- data/test/support/factory.rb +7 -0
- data/test/system/server_tests.rb +21 -3
- data/test/system/service_handler_tests.rb +4 -4
- data/test/unit/cli_tests.rb +2 -2
- data/test/unit/connection_handler_tests.rb +107 -47
- data/test/unit/error_handler_tests.rb +11 -11
- data/test/unit/io_pipe_tests.rb +84 -0
- data/test/unit/process_tests.rb +266 -131
- data/test/unit/router_tests.rb +25 -7
- data/test/unit/server_data_tests.rb +68 -46
- data/test/unit/server_tests.rb +197 -240
- data/test/unit/template_engine_tests.rb +1 -1
- data/test/unit/template_source_tests.rb +6 -0
- data/test/unit/test_runner_tests.rb +0 -19
- metadata +12 -19
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/io_pipe'
|
3
|
+
|
4
|
+
require 'thread'
|
5
|
+
|
6
|
+
class Sanford::IOPipe
|
7
|
+
|
8
|
+
class UnitTests < Assert::Context
|
9
|
+
desc "Sanford::IOPipe"
|
10
|
+
setup do
|
11
|
+
# mimic how IO.select responds
|
12
|
+
@io_select_response = Factory.boolean ? [[NULL], [], []] : nil
|
13
|
+
@io_select_called_with = nil
|
14
|
+
Assert.stub(IO, :select) do |*args|
|
15
|
+
@io_select_called_with = args
|
16
|
+
@io_select_response
|
17
|
+
end
|
18
|
+
|
19
|
+
@io_pipe = Sanford::IOPipe.new
|
20
|
+
end
|
21
|
+
subject{ @io_pipe }
|
22
|
+
|
23
|
+
should have_readers :reader, :writer
|
24
|
+
should have_imeths :setup, :teardown
|
25
|
+
should have_imeths :read, :write, :wait
|
26
|
+
|
27
|
+
should "default its reader and writer" do
|
28
|
+
assert_same NULL, subject.reader
|
29
|
+
assert_same NULL, subject.writer
|
30
|
+
end
|
31
|
+
|
32
|
+
should "change its reader/writer to an IO pipe when setup" do
|
33
|
+
subject.setup
|
34
|
+
assert_not_same NULL, subject.reader
|
35
|
+
assert_not_same NULL, subject.writer
|
36
|
+
assert_instance_of IO, subject.reader
|
37
|
+
assert_instance_of IO, subject.writer
|
38
|
+
end
|
39
|
+
|
40
|
+
should "close its reader/writer and set them to defaults when torn down" do
|
41
|
+
subject.setup
|
42
|
+
reader = subject.reader
|
43
|
+
writer = subject.writer
|
44
|
+
|
45
|
+
subject.teardown
|
46
|
+
assert_true reader.closed?
|
47
|
+
assert_true writer.closed?
|
48
|
+
assert_same NULL, subject.reader
|
49
|
+
assert_same NULL, subject.writer
|
50
|
+
end
|
51
|
+
|
52
|
+
should "be able to read/write values" do
|
53
|
+
subject.setup
|
54
|
+
|
55
|
+
value = Factory.string(NUMBER_OF_BYTES)
|
56
|
+
subject.write(value)
|
57
|
+
assert_equal value, subject.read
|
58
|
+
end
|
59
|
+
|
60
|
+
should "only read/write a fixed number of bytes" do
|
61
|
+
subject.setup
|
62
|
+
|
63
|
+
value = Factory.string
|
64
|
+
subject.write(value)
|
65
|
+
assert_equal value[0, NUMBER_OF_BYTES], subject.read
|
66
|
+
end
|
67
|
+
|
68
|
+
should "be able to wait until there is something to read" do
|
69
|
+
subject.setup
|
70
|
+
|
71
|
+
result = subject.wait
|
72
|
+
exp = [[subject.reader], nil, nil, nil]
|
73
|
+
assert_equal exp, @io_select_called_with
|
74
|
+
assert_equal !!@io_select_response, result
|
75
|
+
|
76
|
+
timeout = Factory.integer
|
77
|
+
subject.wait(timeout)
|
78
|
+
exp = [[subject.reader], nil, nil, timeout]
|
79
|
+
assert_equal exp, @io_select_called_with
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/test/unit/process_tests.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'assert'
|
2
2
|
require 'sanford/process'
|
3
3
|
|
4
|
+
require 'sanford/io_pipe'
|
4
5
|
require 'sanford/server'
|
5
6
|
require 'test/support/pid_file_spy'
|
6
7
|
|
@@ -9,22 +10,37 @@ class Sanford::Process
|
|
9
10
|
class UnitTests < Assert::Context
|
10
11
|
desc "Sanford::Process"
|
11
12
|
setup do
|
13
|
+
@current_env_server_fd = ENV['SANFORD_SERVER_FD']
|
14
|
+
@current_env_client_fds = ENV['SANFORD_CLIENT_FDS']
|
15
|
+
@current_env_skip_daemonize = ENV['SANFORD_SKIP_DAEMONIZE']
|
16
|
+
ENV.delete('SANFORD_SERVER_FD')
|
17
|
+
ENV.delete('SANFORD_CLIENT_FDS')
|
18
|
+
ENV.delete('SANFORD_SKIP_DAEMONIZE')
|
19
|
+
|
12
20
|
@process_class = Sanford::Process
|
13
21
|
end
|
22
|
+
teardown do
|
23
|
+
ENV['SANFORD_SKIP_DAEMONIZE'] = @current_env_skip_daemonize
|
24
|
+
ENV['SANFORD_CLIENT_FDS'] = @current_env_client_fds
|
25
|
+
ENV['SANFORD_SERVER_FD'] = @current_env_server_fd
|
26
|
+
end
|
14
27
|
subject{ @process_class }
|
15
28
|
|
29
|
+
should "know its wait for signals timeout" do
|
30
|
+
assert_equal 15, WAIT_FOR_SIGNALS_TIMEOUT
|
31
|
+
end
|
32
|
+
|
33
|
+
should "know its signal strings" do
|
34
|
+
assert_equal 'H', HALT
|
35
|
+
assert_equal 'S', STOP
|
36
|
+
assert_equal 'R', RESTART
|
37
|
+
end
|
38
|
+
|
16
39
|
end
|
17
40
|
|
18
41
|
class InitTests < UnitTests
|
19
42
|
desc "when init"
|
20
43
|
setup do
|
21
|
-
@current_env_server_fd = ENV['SANFORD_SERVER_FD']
|
22
|
-
@current_env_client_fds = ENV['SANFORD_CLIENT_FDS']
|
23
|
-
@current_env_skip_daemonize = ENV['SANFORD_SKIP_DAEMONIZE']
|
24
|
-
ENV.delete('SANFORD_SERVER_FD')
|
25
|
-
ENV.delete('SANFORD_CLIENT_FDS')
|
26
|
-
ENV.delete('SANFORD_SKIP_DAEMONIZE')
|
27
|
-
|
28
44
|
@server_spy = ServerSpy.new
|
29
45
|
|
30
46
|
@pid_file_spy = PIDFileSpy.new(Factory.integer)
|
@@ -37,14 +53,9 @@ class Sanford::Process
|
|
37
53
|
|
38
54
|
@process = @process_class.new(@server_spy)
|
39
55
|
end
|
40
|
-
teardown do
|
41
|
-
ENV['SANFORD_SKIP_DAEMONIZE'] = @current_env_skip_daemonize
|
42
|
-
ENV['SANFORD_CLIENT_FDS'] = @current_env_client_fds
|
43
|
-
ENV['SANFORD_SERVER_FD'] = @current_env_server_fd
|
44
|
-
end
|
45
56
|
subject{ @process }
|
46
57
|
|
47
|
-
should have_readers :server, :name, :pid_file, :restart_cmd
|
58
|
+
should have_readers :server, :name, :pid_file, :signal_io, :restart_cmd
|
48
59
|
should have_readers :server_ip, :server_port, :server_fd, :client_fds
|
49
60
|
should have_imeths :run, :daemonize?
|
50
61
|
|
@@ -52,16 +63,17 @@ class Sanford::Process
|
|
52
63
|
assert_equal @server_spy, subject.server
|
53
64
|
end
|
54
65
|
|
55
|
-
should "know its name, pid file and restart cmd" do
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
assert_equal @pid_file_spy,
|
60
|
-
|
66
|
+
should "know its name, pid file, signal io and restart cmd" do
|
67
|
+
exp = "sanford: #{@server_spy.process_label}"
|
68
|
+
assert_equal exp, subject.name
|
69
|
+
|
70
|
+
assert_equal @pid_file_spy, subject.pid_file
|
71
|
+
assert_instance_of Sanford::IOPipe, subject.signal_io
|
72
|
+
assert_equal @restart_cmd_spy, subject.restart_cmd
|
61
73
|
end
|
62
74
|
|
63
75
|
should "know its server ip, port and file descriptor" do
|
64
|
-
assert_equal @server_spy.configured_ip,
|
76
|
+
assert_equal @server_spy.configured_ip, subject.server_ip
|
65
77
|
assert_equal @server_spy.configured_port, subject.server_port
|
66
78
|
assert_nil subject.server_fd
|
67
79
|
end
|
@@ -124,28 +136,14 @@ class Sanford::Process
|
|
124
136
|
|
125
137
|
@current_process_name = $0
|
126
138
|
|
127
|
-
@
|
128
|
-
|
129
|
-
|
130
|
-
@term_signal_trap_block = block
|
131
|
-
@term_signal_trap_called = true
|
132
|
-
end
|
133
|
-
|
134
|
-
@int_signal_trap_block = nil
|
135
|
-
@int_signal_trap_called = false
|
136
|
-
Assert.stub(::Signal, :trap).with("INT") do |&block|
|
137
|
-
@int_signal_trap_block = block
|
138
|
-
@int_signal_trap_called = true
|
139
|
-
end
|
140
|
-
|
141
|
-
@usr2_signal_trap_block = nil
|
142
|
-
@usr2_signal_trap_called = false
|
143
|
-
Assert.stub(::Signal, :trap).with("USR2") do |&block|
|
144
|
-
@usr2_signal_trap_block = block
|
145
|
-
@usr2_signal_trap_called = true
|
139
|
+
@signal_traps = []
|
140
|
+
Assert.stub(::Signal, :trap) do |signal, &block|
|
141
|
+
@signal_traps << SignalTrap.new(signal, block)
|
146
142
|
end
|
147
143
|
end
|
148
144
|
teardown do
|
145
|
+
@process.signal_io.write(HALT)
|
146
|
+
@thread.join if @thread
|
149
147
|
$0 = @current_process_name
|
150
148
|
end
|
151
149
|
|
@@ -154,58 +152,74 @@ class Sanford::Process
|
|
154
152
|
class RunTests < RunSetupTests
|
155
153
|
desc "and run"
|
156
154
|
setup do
|
157
|
-
@
|
155
|
+
@wait_timeout = nil
|
156
|
+
Assert.stub(@process.signal_io, :wait) do |timeout|
|
157
|
+
@wait_timeout = timeout
|
158
|
+
sleep 2*JOIN_SECONDS
|
159
|
+
false
|
160
|
+
end
|
161
|
+
|
162
|
+
@thread = Thread.new{ @process.run }
|
163
|
+
@thread.join(JOIN_SECONDS)
|
164
|
+
end
|
165
|
+
teardown do
|
166
|
+
# manually unstub or the process thread will hang forever
|
167
|
+
Assert.unstub(@process.signal_io, :wait)
|
158
168
|
end
|
159
169
|
|
160
|
-
should "not
|
170
|
+
should "not daemonize the process" do
|
161
171
|
assert_false @daemonize_called
|
162
172
|
end
|
163
173
|
|
164
|
-
should "
|
174
|
+
should "start the server listening" do
|
165
175
|
assert_true @server_spy.listen_called
|
166
|
-
|
167
|
-
assert_equal
|
176
|
+
exp = [subject.server_ip, subject.server_port]
|
177
|
+
assert_equal exp, @server_spy.listen_args
|
168
178
|
end
|
169
179
|
|
170
|
-
should "
|
180
|
+
should "set the process name" do
|
171
181
|
assert_equal $0, subject.name
|
172
182
|
end
|
173
183
|
|
174
|
-
should "
|
184
|
+
should "write its PID file" do
|
175
185
|
assert_true @pid_file_spy.write_called
|
176
186
|
end
|
177
187
|
|
178
|
-
should "
|
179
|
-
|
180
|
-
|
181
|
-
@term_signal_trap_block.call
|
182
|
-
assert_true @server_spy.stop_called
|
183
|
-
|
184
|
-
assert_true @int_signal_trap_called
|
185
|
-
assert_false @server_spy.halt_called
|
186
|
-
@int_signal_trap_block.call
|
187
|
-
assert_true @server_spy.halt_called
|
188
|
-
|
189
|
-
assert_true @usr2_signal_trap_called
|
190
|
-
assert_false @server_spy.pause_called
|
191
|
-
@usr2_signal_trap_block.call
|
192
|
-
assert_true @server_spy.pause_called
|
188
|
+
should "trap signals" do
|
189
|
+
assert_equal 3, @signal_traps.size
|
190
|
+
assert_equal ['INT', 'TERM', 'USR2'], @signal_traps.map(&:signal)
|
193
191
|
end
|
194
192
|
|
195
|
-
should "
|
193
|
+
should "start the server" do
|
196
194
|
assert_true @server_spy.start_called
|
197
195
|
end
|
198
196
|
|
199
|
-
should "
|
200
|
-
|
197
|
+
should "sleep its thread waiting for signals" do
|
198
|
+
assert_equal WAIT_FOR_SIGNALS_TIMEOUT, @wait_timeout
|
199
|
+
assert_equal 'sleep', @thread.status
|
201
200
|
end
|
202
201
|
|
203
202
|
should "not run the restart cmd" do
|
204
|
-
|
203
|
+
assert_nil @restart_cmd_spy.run_called_for
|
205
204
|
end
|
206
205
|
|
207
|
-
|
208
|
-
|
206
|
+
end
|
207
|
+
|
208
|
+
class SignalTrapsTests < RunSetupTests
|
209
|
+
desc "signal traps"
|
210
|
+
setup do
|
211
|
+
# setup the io pipe so we can see whats written to it
|
212
|
+
@process.signal_io.setup
|
213
|
+
end
|
214
|
+
teardown do
|
215
|
+
@process.signal_io.teardown
|
216
|
+
end
|
217
|
+
|
218
|
+
should "write the signals to processes signal IO" do
|
219
|
+
@signal_traps.each do |signal_trap|
|
220
|
+
signal_trap.block.call
|
221
|
+
assert_equal signal_trap.signal, subject.signal_io.read
|
222
|
+
end
|
209
223
|
end
|
210
224
|
|
211
225
|
end
|
@@ -214,7 +228,8 @@ class Sanford::Process
|
|
214
228
|
desc "that should daemonize is run"
|
215
229
|
setup do
|
216
230
|
Assert.stub(@process, :daemonize?){ true }
|
217
|
-
@process.run
|
231
|
+
@thread = Thread.new{ @process.run }
|
232
|
+
@thread.join(JOIN_SECONDS)
|
218
233
|
end
|
219
234
|
|
220
235
|
should "have daemonized the process" do
|
@@ -228,13 +243,14 @@ class Sanford::Process
|
|
228
243
|
setup do
|
229
244
|
ENV['SANFORD_SERVER_FD'] = Factory.integer.to_s
|
230
245
|
@process = @process_class.new(@server_spy)
|
231
|
-
@process.run
|
246
|
+
@thread = Thread.new{ @process.run }
|
247
|
+
@thread.join(JOIN_SECONDS)
|
232
248
|
end
|
233
249
|
|
234
250
|
should "have used the file descriptor when listening" do
|
235
251
|
assert_true @server_spy.listen_called
|
236
|
-
|
237
|
-
assert_equal
|
252
|
+
exp = [@process.server_fd]
|
253
|
+
assert_equal exp, @server_spy.listen_args
|
238
254
|
end
|
239
255
|
|
240
256
|
end
|
@@ -245,7 +261,8 @@ class Sanford::Process
|
|
245
261
|
@client_fds = [ Factory.integer, Factory.integer ]
|
246
262
|
ENV['SANFORD_CLIENT_FDS'] = @client_fds.join(',')
|
247
263
|
@process = @process_class.new(@server_spy)
|
248
|
-
@process.run
|
264
|
+
@thread = Thread.new{ @process.run }
|
265
|
+
@thread.join(JOIN_SECONDS)
|
249
266
|
end
|
250
267
|
|
251
268
|
should "have used the client file descriptors when starting" do
|
@@ -255,25 +272,120 @@ class Sanford::Process
|
|
255
272
|
|
256
273
|
end
|
257
274
|
|
258
|
-
class
|
259
|
-
desc "
|
275
|
+
class RunAndHaltTests < RunSetupTests
|
276
|
+
desc "and run with a halt signal"
|
260
277
|
setup do
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
278
|
+
@thread = Thread.new{ @process.run }
|
279
|
+
@thread.join(JOIN_SECONDS)
|
280
|
+
@process.signal_io.write(HALT)
|
281
|
+
@thread.join(JOIN_SECONDS)
|
282
|
+
end
|
283
|
+
|
284
|
+
should "halt its server" do
|
285
|
+
assert_true @server_spy.halt_called
|
286
|
+
assert_equal [true], @server_spy.halt_args
|
287
|
+
end
|
288
|
+
|
289
|
+
should "not set the env var to skip daemonize" do
|
290
|
+
assert_equal @current_env_skip_daemonize, ENV['SANFORD_SKIP_DAEMONIZE']
|
291
|
+
end
|
292
|
+
|
293
|
+
should "not run the restart cmd" do
|
294
|
+
assert_nil @restart_cmd_spy.run_called_for
|
295
|
+
end
|
296
|
+
|
297
|
+
should "remove the PID file" do
|
298
|
+
assert_true @pid_file_spy.remove_called
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
class RunAndStopTests < RunSetupTests
|
304
|
+
desc "and run with a stop signal"
|
305
|
+
setup do
|
306
|
+
@thread = Thread.new{ @process.run }
|
307
|
+
@thread.join(JOIN_SECONDS)
|
308
|
+
@process.signal_io.write(STOP)
|
309
|
+
@thread.join(JOIN_SECONDS)
|
310
|
+
end
|
311
|
+
|
312
|
+
should "stop its server" do
|
313
|
+
assert_true @server_spy.stop_called
|
314
|
+
assert_equal [true], @server_spy.stop_args
|
315
|
+
end
|
316
|
+
|
317
|
+
should "not set the env var to skip daemonize" do
|
318
|
+
assert_equal @current_env_skip_daemonize, ENV['SANFORD_SKIP_DAEMONIZE']
|
319
|
+
end
|
320
|
+
|
321
|
+
should "not run the restart cmd" do
|
322
|
+
assert_nil @restart_cmd_spy.run_called_for
|
323
|
+
end
|
324
|
+
|
325
|
+
should "remove the PID file" do
|
326
|
+
assert_true @pid_file_spy.remove_called
|
327
|
+
end
|
328
|
+
|
329
|
+
end
|
265
330
|
|
266
|
-
|
267
|
-
|
268
|
-
|
331
|
+
class RunAndRestartTests < RunSetupTests
|
332
|
+
desc "and run with a restart signal"
|
333
|
+
setup do
|
334
|
+
@thread = Thread.new{ @process.run }
|
335
|
+
@thread.join(JOIN_SECONDS)
|
336
|
+
@process.signal_io.write(RESTART)
|
337
|
+
@thread.join(JOIN_SECONDS)
|
269
338
|
end
|
270
339
|
|
271
|
-
should "
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
340
|
+
should "pause its server" do
|
341
|
+
assert_true @server_spy.pause_called
|
342
|
+
assert_equal [true], @server_spy.pause_args
|
343
|
+
end
|
344
|
+
|
345
|
+
should "run the restart cmd" do
|
346
|
+
assert_equal @server_spy, @restart_cmd_spy.run_called_for
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
class RunWithServerCrashTests < RunSetupTests
|
352
|
+
desc "and run with the server crashing"
|
353
|
+
setup do
|
354
|
+
Assert.stub(@process.signal_io, :wait) do |timeout|
|
355
|
+
sleep JOIN_SECONDS * 0.5 # ensure this has time to run before the thread
|
356
|
+
# joins below
|
357
|
+
false
|
358
|
+
end
|
359
|
+
|
360
|
+
@thread = Thread.new{ @process.run }
|
361
|
+
@thread.join(JOIN_SECONDS)
|
362
|
+
@server_spy.start_called = false
|
363
|
+
@thread.join(JOIN_SECONDS)
|
364
|
+
end
|
365
|
+
teardown do
|
366
|
+
# manually unstub or the process thread will hang forever
|
367
|
+
Assert.unstub(@process.signal_io, :wait)
|
368
|
+
end
|
369
|
+
|
370
|
+
should "re-start its server" do
|
371
|
+
assert_true @server_spy.start_called
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
class RunWithInvalidSignalTests < RunSetupTests
|
377
|
+
desc "and run with unsupported signals"
|
378
|
+
setup do
|
379
|
+
# ruby throws an argument error if the OS doesn't support a signal
|
380
|
+
Assert.stub(::Signal, :trap){ raise ArgumentError }
|
381
|
+
|
382
|
+
@thread = Thread.new{ @process.run }
|
383
|
+
@thread.join(JOIN_SECONDS)
|
384
|
+
end
|
385
|
+
|
386
|
+
should "start normally" do
|
387
|
+
assert_true @server_spy.start_called
|
388
|
+
assert_equal 'sleep', @thread.status
|
277
389
|
end
|
278
390
|
|
279
391
|
end
|
@@ -289,6 +401,12 @@ class Sanford::Process
|
|
289
401
|
Assert.stub(File, :stat).with(Dir.pwd){ @ruby_pwd_stat }
|
290
402
|
Assert.stub(File, :stat).with(ENV['PWD']){ env_pwd_stat }
|
291
403
|
|
404
|
+
@server_spy = ServerSpy.new
|
405
|
+
server_fd = Factory.integer
|
406
|
+
Assert.stub(@server_spy, :file_descriptor){ server_fd }
|
407
|
+
client_fds = Factory.integer(3).times.map{ Factory.integer }
|
408
|
+
Assert.stub(@server_spy, :client_file_descriptors){ client_fds }
|
409
|
+
|
292
410
|
@chdir_called_with = nil
|
293
411
|
Assert.stub(Dir, :chdir){ |*args| @chdir_called_with = args }
|
294
412
|
|
@@ -317,10 +435,38 @@ class Sanford::Process
|
|
317
435
|
assert_equal [Gem.ruby, $0, ARGV].flatten, subject.argv
|
318
436
|
end
|
319
437
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
438
|
+
if RUBY_VERSION == '1.8.7'
|
439
|
+
|
440
|
+
should "set env vars, change the dir and kernel exec when run" do
|
441
|
+
subject.run(@server_spy)
|
442
|
+
|
443
|
+
assert_equal @server_spy.file_descriptor.to_s, ENV['SANFORD_SERVER_FD']
|
444
|
+
exp = @server_spy.client_file_descriptors.join(',')
|
445
|
+
assert_equal exp, ENV['SANFORD_CLIENT_FDS']
|
446
|
+
assert_equal 'yes', ENV['SANFORD_SKIP_DAEMONIZE']
|
447
|
+
|
448
|
+
assert_equal [subject.dir], @chdir_called_with
|
449
|
+
assert_equal subject.argv, @exec_called_with
|
450
|
+
end
|
451
|
+
|
452
|
+
else
|
453
|
+
|
454
|
+
should "kernel exec when run" do
|
455
|
+
subject.run(@server_spy)
|
456
|
+
|
457
|
+
env = {
|
458
|
+
'SANFORD_SERVER_FD' => @server_spy.file_descriptor.to_s,
|
459
|
+
'SANFORD_CLIENT_FDS' => @server_spy.client_file_descriptors.join(','),
|
460
|
+
'SANFORD_SKIP_DAEMONIZE' => 'yes'
|
461
|
+
}
|
462
|
+
fd_redirects = (
|
463
|
+
[@server_spy.file_descriptor] +
|
464
|
+
@server_spy.client_file_descriptors
|
465
|
+
).inject({}){ |h, fd| h.merge!(fd => fd) }
|
466
|
+
options = { :chdir => subject.dir }.merge!(fd_redirects)
|
467
|
+
assert_equal ([env] + subject.argv + [options]), @exec_called_with
|
468
|
+
end
|
469
|
+
|
324
470
|
end
|
325
471
|
|
326
472
|
end
|
@@ -364,31 +510,35 @@ class Sanford::Process
|
|
364
510
|
|
365
511
|
end
|
366
512
|
|
513
|
+
SignalTrap = Struct.new(:signal, :block)
|
514
|
+
|
367
515
|
class ServerSpy
|
368
516
|
include Sanford::Server
|
369
517
|
|
370
|
-
name
|
371
|
-
ip
|
372
|
-
port
|
518
|
+
name Factory.string
|
519
|
+
ip Factory.string
|
520
|
+
port Factory.integer
|
373
521
|
pid_file Factory.file_path
|
374
522
|
|
375
|
-
|
376
|
-
|
377
|
-
attr_reader :listen_args, :start_args
|
378
|
-
attr_reader :thread
|
523
|
+
attr_accessor :process_label, :listen_called
|
524
|
+
attr_accessor :start_called, :stop_called, :halt_called, :pause_called
|
525
|
+
attr_reader :listen_args, :start_args, :stop_args, :halt_args, :pause_args
|
379
526
|
|
380
527
|
def initialize(*args)
|
381
528
|
super
|
382
|
-
@listen_called = false
|
383
|
-
@start_called = false
|
384
|
-
@stop_called = false
|
385
|
-
@halt_called = false
|
386
|
-
@pause_called = false
|
387
529
|
|
388
|
-
@
|
389
|
-
@start_args = nil
|
530
|
+
@process_label = Factory.string
|
390
531
|
|
391
|
-
@
|
532
|
+
@listen_args = nil
|
533
|
+
@listen_called = false
|
534
|
+
@start_args = nil
|
535
|
+
@start_called = false
|
536
|
+
@stop_args = nil
|
537
|
+
@stop_called = false
|
538
|
+
@halt_args = nil
|
539
|
+
@halt_called = false
|
540
|
+
@pause_args = nil
|
541
|
+
@pause_called = false
|
392
542
|
end
|
393
543
|
|
394
544
|
def listen(*args)
|
@@ -399,53 +549,38 @@ class Sanford::Process
|
|
399
549
|
def start(*args)
|
400
550
|
@start_args = args
|
401
551
|
@start_called = true
|
402
|
-
@thread
|
403
552
|
end
|
404
553
|
|
405
554
|
def stop(*args)
|
555
|
+
@stop_args = args
|
406
556
|
@stop_called = true
|
407
557
|
end
|
408
558
|
|
409
559
|
def halt(*args)
|
560
|
+
@halt_args = args
|
410
561
|
@halt_called = true
|
411
562
|
end
|
412
563
|
|
564
|
+
|
413
565
|
def pause(*args)
|
566
|
+
@pause_args = args
|
414
567
|
@pause_called = true
|
415
568
|
end
|
416
569
|
|
417
|
-
def
|
418
|
-
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
class ThreadSpy
|
423
|
-
attr_reader :join_called, :on_join_proc
|
424
|
-
|
425
|
-
def initialize
|
426
|
-
@join_called = false
|
427
|
-
@on_join_proc = proc{ }
|
428
|
-
end
|
429
|
-
|
430
|
-
def on_join(&block)
|
431
|
-
@on_join_proc = block
|
432
|
-
end
|
433
|
-
|
434
|
-
def join
|
435
|
-
@join_called = true
|
436
|
-
@on_join_proc.call
|
570
|
+
def running?
|
571
|
+
!!@start_called
|
437
572
|
end
|
438
573
|
end
|
439
574
|
|
440
575
|
class RestartCmdSpy
|
441
|
-
attr_reader :
|
576
|
+
attr_reader :run_called_for
|
442
577
|
|
443
578
|
def initialize
|
444
|
-
@
|
579
|
+
@run_called_for = nil
|
445
580
|
end
|
446
581
|
|
447
|
-
def run
|
448
|
-
@
|
582
|
+
def run(server)
|
583
|
+
@run_called_for = server
|
449
584
|
end
|
450
585
|
end
|
451
586
|
|