sanford 0.10.1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/README.md +41 -56
- data/Rakefile +0 -1
- data/bench/client.rb +8 -3
- data/bench/{services.rb → config.sanford} +11 -6
- data/bench/{runner.rb → report.rb} +2 -2
- data/bench/report.txt +32 -32
- data/lib/sanford/cli.rb +42 -28
- data/lib/sanford/config_file.rb +79 -0
- data/lib/sanford/{worker.rb → connection_handler.rb} +28 -20
- data/lib/sanford/error_handler.rb +7 -7
- data/lib/sanford/pid_file.rb +42 -0
- data/lib/sanford/process.rb +136 -0
- data/lib/sanford/process_signal.rb +20 -0
- data/lib/sanford/route.rb +48 -0
- data/lib/sanford/router.rb +36 -0
- data/lib/sanford/runner.rb +30 -58
- data/lib/sanford/sanford_runner.rb +19 -9
- data/lib/sanford/server.rb +211 -42
- data/lib/sanford/server_data.rb +47 -0
- data/lib/sanford/service_handler.rb +8 -46
- data/lib/sanford/template_source.rb +19 -2
- data/lib/sanford/test_runner.rb +27 -28
- data/lib/sanford/version.rb +1 -1
- data/lib/sanford.rb +1 -23
- data/sanford.gemspec +4 -5
- data/test/helper.rb +3 -20
- data/test/support/app_server.rb +142 -0
- data/test/support/config.sanford +7 -0
- data/test/support/config_invalid_run.sanford +3 -0
- data/test/support/config_no_run.sanford +0 -0
- data/test/support/fake_server_connection.rb +58 -0
- data/test/support/pid_file_spy.rb +19 -0
- data/test/support/template.erb +1 -0
- data/test/system/server_tests.rb +378 -0
- data/test/system/service_handler_tests.rb +224 -0
- data/test/unit/cli_tests.rb +187 -0
- data/test/unit/config_file_tests.rb +59 -0
- data/test/unit/connection_handler_tests.rb +254 -0
- data/test/unit/error_handler_tests.rb +30 -35
- data/test/unit/pid_file_tests.rb +70 -0
- data/test/unit/process_signal_tests.rb +61 -0
- data/test/unit/process_tests.rb +428 -0
- data/test/unit/route_tests.rb +92 -0
- data/test/unit/router_tests.rb +65 -0
- data/test/unit/runner_tests.rb +61 -15
- data/test/unit/sanford_runner_tests.rb +162 -28
- data/test/unit/sanford_tests.rb +0 -8
- data/test/unit/server_data_tests.rb +87 -0
- data/test/unit/server_tests.rb +502 -21
- data/test/unit/service_handler_tests.rb +114 -219
- data/test/unit/template_engine_tests.rb +1 -1
- data/test/unit/template_source_tests.rb +56 -16
- data/test/unit/test_runner_tests.rb +206 -0
- metadata +67 -67
- data/bench/tasks.rb +0 -41
- data/lib/sanford/config.rb +0 -28
- data/lib/sanford/host.rb +0 -129
- data/lib/sanford/host_data.rb +0 -65
- data/lib/sanford/hosts.rb +0 -38
- data/lib/sanford/manager.rb +0 -275
- data/test/support/fake_connection.rb +0 -36
- data/test/support/helpers.rb +0 -17
- data/test/support/service_handlers.rb +0 -154
- data/test/support/services.rb +0 -123
- data/test/support/simple_client.rb +0 -62
- data/test/system/request_handling_tests.rb +0 -306
- data/test/unit/config_tests.rb +0 -56
- data/test/unit/host_data_tests.rb +0 -71
- data/test/unit/host_tests.rb +0 -141
- data/test/unit/hosts_tests.rb +0 -50
- data/test/unit/manager_tests.rb +0 -195
- data/test/unit/worker_tests.rb +0 -24
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/pid_file'
|
3
|
+
|
4
|
+
class Sanford::PIDFile
|
5
|
+
|
6
|
+
class UnitTests < Assert::Context
|
7
|
+
desc "Sanford::PIDFile"
|
8
|
+
setup do
|
9
|
+
@path = ROOT_PATH.join('tmp/pid_file_tests.pid').to_s
|
10
|
+
@pid_file = Sanford::PIDFile.new(@path)
|
11
|
+
end
|
12
|
+
teardown do
|
13
|
+
FileUtils.rm_rf(@path)
|
14
|
+
end
|
15
|
+
subject{ @pid_file }
|
16
|
+
|
17
|
+
should have_readers :path
|
18
|
+
should have_imeths :pid, :write, :remove, :to_s
|
19
|
+
|
20
|
+
should "know its path" do
|
21
|
+
assert_equal @path, subject.path
|
22
|
+
end
|
23
|
+
|
24
|
+
should "default its path" do
|
25
|
+
pid_file = Sanford::PIDFile.new(nil)
|
26
|
+
assert_equal '/dev/null', pid_file.path
|
27
|
+
end
|
28
|
+
|
29
|
+
should "know its string format" do
|
30
|
+
assert_equal @path, subject.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
should "read a PID from its file" do
|
34
|
+
pid = Factory.integer
|
35
|
+
File.open(@path, 'w'){ |f| f.puts pid }
|
36
|
+
assert_equal pid, subject.pid
|
37
|
+
end
|
38
|
+
|
39
|
+
should "raise an invalid error when it can't read from its file" do
|
40
|
+
FileUtils.rm_rf(@path)
|
41
|
+
assert_raises(InvalidError){ subject.pid }
|
42
|
+
end
|
43
|
+
|
44
|
+
should "raise an invalid error when the file doesn't have a PID in it" do
|
45
|
+
File.open(@path, 'w'){ |f| f.puts '' }
|
46
|
+
assert_raises(InvalidError){ subject.pid }
|
47
|
+
end
|
48
|
+
|
49
|
+
should "write the process PID to its file" do
|
50
|
+
assert_false File.exists?(@path)
|
51
|
+
subject.write
|
52
|
+
assert_true File.exists?(@path)
|
53
|
+
assert_equal "#{::Process.pid}\n", File.read(@path)
|
54
|
+
end
|
55
|
+
|
56
|
+
should "raise an invalid error when it can't write its file" do
|
57
|
+
Assert.stub(File, :open){ raise "can't open file" }
|
58
|
+
assert_raises(InvalidError){ subject.write }
|
59
|
+
end
|
60
|
+
|
61
|
+
should "remove its file" do
|
62
|
+
FileUtils.touch(@path)
|
63
|
+
assert_true File.exists?(@path)
|
64
|
+
subject.remove
|
65
|
+
assert_false File.exists?(@path)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/process_signal'
|
3
|
+
|
4
|
+
require 'sanford/server'
|
5
|
+
require 'test/support/pid_file_spy'
|
6
|
+
|
7
|
+
class Sanford::ProcessSignal
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "Sanford::ProcessSignal"
|
11
|
+
setup do
|
12
|
+
@server = TestServer.new
|
13
|
+
@signal = Factory.string
|
14
|
+
|
15
|
+
@pid_file_spy = PIDFileSpy.new(Factory.integer)
|
16
|
+
Assert.stub(Sanford::PIDFile, :new).with(@server.pid_file) do
|
17
|
+
@pid_file_spy
|
18
|
+
end
|
19
|
+
|
20
|
+
@process_signal = Sanford::ProcessSignal.new(@server, @signal)
|
21
|
+
end
|
22
|
+
subject{ @process_signal }
|
23
|
+
|
24
|
+
should have_readers :signal, :pid
|
25
|
+
should have_imeths :send
|
26
|
+
|
27
|
+
should "know its signal and pid" do
|
28
|
+
assert_equal @signal, subject.signal
|
29
|
+
assert_equal @pid_file_spy.pid, subject.pid
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class SendTests < UnitTests
|
35
|
+
desc "when sent"
|
36
|
+
setup do
|
37
|
+
@kill_called = false
|
38
|
+
Assert.stub(::Process, :kill).with(@signal, @pid_file_spy.pid) do
|
39
|
+
@kill_called = true
|
40
|
+
end
|
41
|
+
|
42
|
+
@process_signal.send
|
43
|
+
end
|
44
|
+
|
45
|
+
should "have used process kill to send the signal to the PID" do
|
46
|
+
assert_true @kill_called
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class TestServer
|
52
|
+
include Sanford::Server
|
53
|
+
|
54
|
+
name Factory.string
|
55
|
+
ip Factory.string
|
56
|
+
port Factory.integer
|
57
|
+
pid_file Factory.file_path
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,428 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/process'
|
3
|
+
|
4
|
+
require 'sanford/server'
|
5
|
+
require 'test/support/pid_file_spy'
|
6
|
+
|
7
|
+
class Sanford::Process
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "Sanford::Process"
|
11
|
+
setup do
|
12
|
+
@process_class = Sanford::Process
|
13
|
+
end
|
14
|
+
subject{ @process_class }
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class InitTests < UnitTests
|
19
|
+
desc "when init"
|
20
|
+
setup do
|
21
|
+
@current_env_ip = ENV['SANFORD_IP']
|
22
|
+
@current_env_port = ENV['SANFORD_PORT']
|
23
|
+
@current_env_server_fd = ENV['SANFORD_SERVER_FD']
|
24
|
+
@current_env_client_fds = ENV['SANFORD_CLIENT_FDS']
|
25
|
+
@current_env_skip_daemonize = ENV['SANFORD_SKIP_DAEMONIZE']
|
26
|
+
ENV.delete('SANFORD_IP')
|
27
|
+
ENV.delete('SANFORD_PORT')
|
28
|
+
ENV.delete('SANFORD_SERVER_FD')
|
29
|
+
ENV.delete('SANFORD_CLIENT_FDS')
|
30
|
+
ENV.delete('SANFORD_SKIP_DAEMONIZE')
|
31
|
+
|
32
|
+
@server_spy = ServerSpy.new
|
33
|
+
|
34
|
+
@pid_file_spy = PIDFileSpy.new(Factory.integer)
|
35
|
+
Assert.stub(Sanford::PIDFile, :new).with(@server_spy.pid_file) do
|
36
|
+
@pid_file_spy
|
37
|
+
end
|
38
|
+
|
39
|
+
@restart_cmd_spy = RestartCmdSpy.new
|
40
|
+
Assert.stub(Sanford::RestartCmd, :new){ @restart_cmd_spy }
|
41
|
+
|
42
|
+
@process = @process_class.new(@server_spy)
|
43
|
+
end
|
44
|
+
teardown do
|
45
|
+
ENV['SANFORD_SKIP_DAEMONIZE'] = @current_env_skip_daemonize
|
46
|
+
ENV['SANFORD_CLIENT_FDS'] = @current_env_client_fds
|
47
|
+
ENV['SANFORD_SERVER_FD'] = @current_env_server_fd
|
48
|
+
ENV['SANFORD_PORT'] = @current_env_ip
|
49
|
+
ENV['SANFORD_IP'] = @current_env_port
|
50
|
+
end
|
51
|
+
subject{ @process }
|
52
|
+
|
53
|
+
should have_readers :server, :name, :pid_file, :restart_cmd
|
54
|
+
should have_readers :server_ip, :server_port, :server_fd, :client_fds
|
55
|
+
should have_imeths :run, :daemonize?
|
56
|
+
|
57
|
+
should "know its server" do
|
58
|
+
assert_equal @server_spy, subject.server
|
59
|
+
end
|
60
|
+
|
61
|
+
should "know its name, pid file and restart cmd" do
|
62
|
+
assert_equal "sanford-#{@server_spy.name}", subject.name
|
63
|
+
assert_equal @pid_file_spy, subject.pid_file
|
64
|
+
assert_equal @restart_cmd_spy, subject.restart_cmd
|
65
|
+
end
|
66
|
+
|
67
|
+
should "know its server ip, port and file descriptor" do
|
68
|
+
assert_nil subject.server_ip
|
69
|
+
assert_nil subject.server_port
|
70
|
+
assert_nil subject.server_fd
|
71
|
+
end
|
72
|
+
|
73
|
+
should "set its server ip, port and file descriptor using env vars" do
|
74
|
+
ENV['SANFORD_IP'] = Factory.string
|
75
|
+
ENV['SANFORD_PORT'] = Factory.integer.to_s
|
76
|
+
ENV['SANFORD_SERVER_FD'] = Factory.integer.to_s
|
77
|
+
process = @process_class.new(@server_spy)
|
78
|
+
assert_equal ENV['SANFORD_IP'], process.server_ip
|
79
|
+
assert_equal ENV['SANFORD_PORT'].to_i, process.server_port
|
80
|
+
assert_equal ENV['SANFORD_SERVER_FD'].to_i, process.server_fd
|
81
|
+
end
|
82
|
+
|
83
|
+
should "ignore blank env values for its server ip, port and fd" do
|
84
|
+
ENV['SANFORD_IP'] = ''
|
85
|
+
ENV['SANFORD_PORT'] = ''
|
86
|
+
ENV['SANFORD_SERVER_FD'] = ''
|
87
|
+
process = @process_class.new(@server_spy)
|
88
|
+
assert_nil process.server_ip
|
89
|
+
assert_nil process.server_port
|
90
|
+
assert_nil process.server_fd
|
91
|
+
end
|
92
|
+
|
93
|
+
should "know its client file descriptors" do
|
94
|
+
assert_equal [], subject.client_fds
|
95
|
+
end
|
96
|
+
|
97
|
+
should "set its client file descriptors using an env var" do
|
98
|
+
client_fds = [ Factory.integer, Factory.integer ]
|
99
|
+
ENV['SANFORD_CLIENT_FDS'] = client_fds.join(',')
|
100
|
+
process = @process_class.new(@server_spy)
|
101
|
+
assert_equal client_fds, process.client_fds
|
102
|
+
end
|
103
|
+
|
104
|
+
should "not daemonize by default" do
|
105
|
+
process = @process_class.new(@server_spy)
|
106
|
+
assert_false subject.daemonize?
|
107
|
+
end
|
108
|
+
|
109
|
+
should "daemonize if turned on" do
|
110
|
+
process = @process_class.new(@server_spy, :daemonize => true)
|
111
|
+
assert_true process.daemonize?
|
112
|
+
end
|
113
|
+
|
114
|
+
should "not daemonize if skipped via the env var" do
|
115
|
+
ENV['SANFORD_SKIP_DAEMONIZE'] = 'yes'
|
116
|
+
process = @process_class.new(@server_spy)
|
117
|
+
assert_false process.daemonize?
|
118
|
+
process = @process_class.new(@server_spy, :daemonize => true)
|
119
|
+
assert_false process.daemonize?
|
120
|
+
end
|
121
|
+
|
122
|
+
should "ignore blank env values for skip daemonize" do
|
123
|
+
ENV['SANFORD_SKIP_DAEMONIZE'] = ''
|
124
|
+
process = @process_class.new(@server_spy, :daemonize => true)
|
125
|
+
assert_true process.daemonize?
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
class RunSetupTests < InitTests
|
131
|
+
setup do
|
132
|
+
@daemonize_called = false
|
133
|
+
Assert.stub(::Process, :daemon).with(true){ @daemonize_called = true }
|
134
|
+
|
135
|
+
@current_process_name = $0
|
136
|
+
|
137
|
+
@term_signal_trap_block = nil
|
138
|
+
@term_signal_trap_called = false
|
139
|
+
Assert.stub(::Signal, :trap).with("TERM") do |&block|
|
140
|
+
@term_signal_trap_block = block
|
141
|
+
@term_signal_trap_called = true
|
142
|
+
end
|
143
|
+
|
144
|
+
@int_signal_trap_block = nil
|
145
|
+
@int_signal_trap_called = false
|
146
|
+
Assert.stub(::Signal, :trap).with("INT") do |&block|
|
147
|
+
@int_signal_trap_block = block
|
148
|
+
@int_signal_trap_called = true
|
149
|
+
end
|
150
|
+
|
151
|
+
@usr2_signal_trap_block = nil
|
152
|
+
@usr2_signal_trap_called = false
|
153
|
+
Assert.stub(::Signal, :trap).with("USR2") do |&block|
|
154
|
+
@usr2_signal_trap_block = block
|
155
|
+
@usr2_signal_trap_called = true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
teardown do
|
159
|
+
$0 = @current_process_name
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
class RunTests < RunSetupTests
|
165
|
+
desc "and run"
|
166
|
+
setup do
|
167
|
+
@process.run
|
168
|
+
end
|
169
|
+
|
170
|
+
should "not have daemonized the process" do
|
171
|
+
assert_false @daemonize_called
|
172
|
+
end
|
173
|
+
|
174
|
+
should "have started the server listening" do
|
175
|
+
assert_true @server_spy.listen_called
|
176
|
+
assert_equal [], @server_spy.listen_args
|
177
|
+
end
|
178
|
+
|
179
|
+
should "have set the process name" do
|
180
|
+
assert_equal $0, subject.name
|
181
|
+
end
|
182
|
+
|
183
|
+
should "have written the PID file" do
|
184
|
+
assert_true @pid_file_spy.write_called
|
185
|
+
end
|
186
|
+
|
187
|
+
should "have trapped signals" do
|
188
|
+
assert_true @term_signal_trap_called
|
189
|
+
assert_false @server_spy.stop_called
|
190
|
+
@term_signal_trap_block.call
|
191
|
+
assert_true @server_spy.stop_called
|
192
|
+
|
193
|
+
assert_true @int_signal_trap_called
|
194
|
+
assert_false @server_spy.halt_called
|
195
|
+
@int_signal_trap_block.call
|
196
|
+
assert_true @server_spy.halt_called
|
197
|
+
|
198
|
+
assert_true @usr2_signal_trap_called
|
199
|
+
assert_false @server_spy.pause_called
|
200
|
+
@usr2_signal_trap_block.call
|
201
|
+
assert_true @server_spy.pause_called
|
202
|
+
end
|
203
|
+
|
204
|
+
should "have started the server" do
|
205
|
+
assert_true @server_spy.start_called
|
206
|
+
end
|
207
|
+
|
208
|
+
should "have joined the server thread" do
|
209
|
+
assert_true @server_spy.thread.join_called
|
210
|
+
end
|
211
|
+
|
212
|
+
should "not have exec'd the restart cmd" do
|
213
|
+
assert_false @restart_cmd_spy.exec_called
|
214
|
+
end
|
215
|
+
|
216
|
+
should "have removed the PID file" do
|
217
|
+
assert_true @pid_file_spy.remove_called
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
class RunWithDaemonizeTests < RunSetupTests
|
223
|
+
desc "that should daemonize is run"
|
224
|
+
setup do
|
225
|
+
Assert.stub(@process, :daemonize?){ true }
|
226
|
+
@process.run
|
227
|
+
end
|
228
|
+
|
229
|
+
should "have daemonized the process" do
|
230
|
+
assert_true @daemonize_called
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
class RunWithIPAndPortTests < RunSetupTests
|
236
|
+
desc "with a custom IP and port is run"
|
237
|
+
setup do
|
238
|
+
ENV['SANFORD_IP'] = Factory.string
|
239
|
+
ENV['SANFORD_PORT'] = Factory.integer.to_s
|
240
|
+
@process = @process_class.new(@server_spy)
|
241
|
+
@process.run
|
242
|
+
end
|
243
|
+
|
244
|
+
should "have used the custom IP and port when listening" do
|
245
|
+
assert_true @server_spy.listen_called
|
246
|
+
expected = [ @process.server_ip, @process.server_port ]
|
247
|
+
assert_equal expected, @server_spy.listen_args
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
class RunWithServerFDTests < RunSetupTests
|
253
|
+
desc "with a server file descriptor is run"
|
254
|
+
setup do
|
255
|
+
ENV['SANFORD_SERVER_FD'] = Factory.integer.to_s
|
256
|
+
@process = @process_class.new(@server_spy)
|
257
|
+
@process.run
|
258
|
+
end
|
259
|
+
|
260
|
+
should "have used the file descriptor when listening" do
|
261
|
+
assert_true @server_spy.listen_called
|
262
|
+
expected = [ @process.server_fd ]
|
263
|
+
assert_equal expected, @server_spy.listen_args
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
class RunWithClientFDsTests < RunSetupTests
|
269
|
+
desc "with client file descriptors is run"
|
270
|
+
setup do
|
271
|
+
@client_fds = [ Factory.integer, Factory.integer ]
|
272
|
+
ENV['SANFORD_CLIENT_FDS'] = @client_fds.join(',')
|
273
|
+
@process = @process_class.new(@server_spy)
|
274
|
+
@process.run
|
275
|
+
end
|
276
|
+
|
277
|
+
should "have used the client file descriptors when starting" do
|
278
|
+
assert_true @server_spy.start_called
|
279
|
+
assert_equal [ @client_fds ], @server_spy.start_args
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
class RunAndServerPausedTests < RunSetupTests
|
285
|
+
desc "then run and then paused"
|
286
|
+
setup do
|
287
|
+
server_fd = Factory.integer
|
288
|
+
Assert.stub(@server_spy, :file_descriptor){ server_fd }
|
289
|
+
client_fds = [ Factory.integer, Factory.integer ]
|
290
|
+
Assert.stub(@server_spy, :client_file_descriptors){ client_fds }
|
291
|
+
|
292
|
+
# mimicing pause being called by a signal, after the thread is joined
|
293
|
+
@server_spy.thread.on_join{ @server_spy.pause }
|
294
|
+
@process.run
|
295
|
+
end
|
296
|
+
|
297
|
+
should "have set env vars for execing the restart cmd" do
|
298
|
+
assert_equal @server_spy.file_descriptor.to_s, ENV['SANFORD_SERVER_FD']
|
299
|
+
expected = @server_spy.client_file_descriptors.join(',')
|
300
|
+
assert_equal expected, ENV['SANFORD_CLIENT_FDS']
|
301
|
+
assert_equal 'yes', ENV['SANFORD_SKIP_DAEMONIZE']
|
302
|
+
end
|
303
|
+
|
304
|
+
should "have exec'd the restart cmd" do
|
305
|
+
assert_true @restart_cmd_spy.exec_called
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
class RestartCmdTests < UnitTests
|
311
|
+
desc "RestartCmd"
|
312
|
+
setup do
|
313
|
+
@restart_cmd = Sanford::RestartCmd.new
|
314
|
+
|
315
|
+
@chdir_called = false
|
316
|
+
Assert.stub(Dir, :chdir).with(@restart_cmd.dir){ @chdir_called = true }
|
317
|
+
|
318
|
+
@exec_called = false
|
319
|
+
Assert.stub(Kernel, :exec).with(*@restart_cmd.argv){ @exec_called = true }
|
320
|
+
end
|
321
|
+
subject{ @restart_cmd }
|
322
|
+
|
323
|
+
should have_readers :argv, :dir
|
324
|
+
|
325
|
+
should "know its argv and dir" do
|
326
|
+
expected = [ Gem.ruby, $0, ARGV ].flatten
|
327
|
+
assert_equal expected, subject.argv
|
328
|
+
assert_equal Dir.pwd, subject.dir
|
329
|
+
end
|
330
|
+
|
331
|
+
should "change the dir when exec'd" do
|
332
|
+
subject.exec
|
333
|
+
assert_true @chdir_called
|
334
|
+
end
|
335
|
+
|
336
|
+
should "kernel exec its argv when exec'd" do
|
337
|
+
subject.exec
|
338
|
+
assert_true @exec_called
|
339
|
+
end
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
class ServerSpy
|
344
|
+
include Sanford::Server
|
345
|
+
|
346
|
+
name Factory.string
|
347
|
+
ip Factory.string
|
348
|
+
port Factory.integer
|
349
|
+
pid_file Factory.file_path
|
350
|
+
|
351
|
+
attr_reader :listen_called, :start_called
|
352
|
+
attr_reader :stop_called, :halt_called, :pause_called
|
353
|
+
attr_reader :listen_args, :start_args
|
354
|
+
attr_reader :thread
|
355
|
+
|
356
|
+
def initialize(*args)
|
357
|
+
super
|
358
|
+
@listen_called = false
|
359
|
+
@start_called = false
|
360
|
+
@stop_called = false
|
361
|
+
@halt_called = false
|
362
|
+
@pause_called = false
|
363
|
+
|
364
|
+
@listen_args = nil
|
365
|
+
@start_args = nil
|
366
|
+
|
367
|
+
@thread = ThreadSpy.new
|
368
|
+
end
|
369
|
+
|
370
|
+
def listen(*args)
|
371
|
+
@listen_args = args
|
372
|
+
@listen_called = true
|
373
|
+
end
|
374
|
+
|
375
|
+
def start(*args)
|
376
|
+
@start_args = args
|
377
|
+
@start_called = true
|
378
|
+
@thread
|
379
|
+
end
|
380
|
+
|
381
|
+
def stop(*args)
|
382
|
+
@stop_called = true
|
383
|
+
end
|
384
|
+
|
385
|
+
def halt(*args)
|
386
|
+
@halt_called = true
|
387
|
+
end
|
388
|
+
|
389
|
+
def pause(*args)
|
390
|
+
@pause_called = true
|
391
|
+
end
|
392
|
+
|
393
|
+
def paused?
|
394
|
+
@pause_called
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
class ThreadSpy
|
399
|
+
attr_reader :join_called, :on_join_proc
|
400
|
+
|
401
|
+
def initialize
|
402
|
+
@join_called = false
|
403
|
+
@on_join_proc = proc{ }
|
404
|
+
end
|
405
|
+
|
406
|
+
def on_join(&block)
|
407
|
+
@on_join_proc = block
|
408
|
+
end
|
409
|
+
|
410
|
+
def join
|
411
|
+
@join_called = true
|
412
|
+
@on_join_proc.call
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
class RestartCmdSpy
|
417
|
+
attr_reader :exec_called
|
418
|
+
|
419
|
+
def initialize
|
420
|
+
@exec_called = false
|
421
|
+
end
|
422
|
+
|
423
|
+
def exec
|
424
|
+
@exec_called = true
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/route'
|
3
|
+
|
4
|
+
require 'sanford/server_data'
|
5
|
+
require 'sanford/service_handler'
|
6
|
+
|
7
|
+
class Sanford::Route
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "Sanford::Route"
|
11
|
+
setup do
|
12
|
+
@name = Factory.string
|
13
|
+
@handler_class_name = TestHandler.to_s
|
14
|
+
@route = Sanford::Route.new(@name, @handler_class_name)
|
15
|
+
end
|
16
|
+
subject{ @route }
|
17
|
+
|
18
|
+
should have_readers :name, :handler_class_name, :handler_class
|
19
|
+
|
20
|
+
should "know its name and handler class name" do
|
21
|
+
assert_equal @name, subject.name
|
22
|
+
assert_equal @handler_class_name, subject.handler_class_name
|
23
|
+
end
|
24
|
+
|
25
|
+
should "not know its handler class by default" do
|
26
|
+
assert_nil subject.handler_class
|
27
|
+
end
|
28
|
+
|
29
|
+
should "constantize its handler class after being validated" do
|
30
|
+
subject.validate!
|
31
|
+
assert_equal TestHandler, subject.handler_class
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class RunTests < UnitTests
|
37
|
+
desc "when run"
|
38
|
+
setup do
|
39
|
+
@route.validate!
|
40
|
+
@request = Factory.string
|
41
|
+
@server_data = Sanford::ServerData.new
|
42
|
+
|
43
|
+
@runner_spy = RunnerSpy.new(Factory.text)
|
44
|
+
Assert.stub(Sanford::SanfordRunner, :new).with(
|
45
|
+
@route.handler_class,
|
46
|
+
@request,
|
47
|
+
@server_data
|
48
|
+
){ @runner_spy }
|
49
|
+
|
50
|
+
@response = @route.run(@request, @server_data)
|
51
|
+
end
|
52
|
+
subject{ @response }
|
53
|
+
|
54
|
+
should "build and run a sanford runner" do
|
55
|
+
assert_true @runner_spy.run_called
|
56
|
+
end
|
57
|
+
|
58
|
+
should "return the response from the running the runner" do
|
59
|
+
assert_equal @runner_spy.response, subject
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class InvalidHandlerClassNameTests < UnitTests
|
65
|
+
desc "with an invalid handler class name"
|
66
|
+
setup do
|
67
|
+
@route = Sanford::Route.new(@name, Factory.string)
|
68
|
+
end
|
69
|
+
|
70
|
+
should "raise a no handler class error when validated" do
|
71
|
+
assert_raises(Sanford::NoHandlerClassError){ subject.validate! }
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
TestHandler = Class.new
|
77
|
+
|
78
|
+
class RunnerSpy
|
79
|
+
attr_reader :response, :run_called
|
80
|
+
|
81
|
+
def initialize(response)
|
82
|
+
@response = response
|
83
|
+
@run_called = false
|
84
|
+
end
|
85
|
+
|
86
|
+
def run
|
87
|
+
@run_called = true
|
88
|
+
@response
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'sanford/router'
|
3
|
+
|
4
|
+
require 'test/support/factory'
|
5
|
+
|
6
|
+
class Sanford::Router
|
7
|
+
|
8
|
+
class UnitTests < Assert::Context
|
9
|
+
desc "Sanford::Host"
|
10
|
+
setup do
|
11
|
+
@router = Sanford::Router.new
|
12
|
+
end
|
13
|
+
subject{ @router }
|
14
|
+
|
15
|
+
should have_readers :routes
|
16
|
+
should have_imeths :service_handler_ns, :service
|
17
|
+
|
18
|
+
should "build an empty array for its routes by default" do
|
19
|
+
assert_equal [], subject.routes
|
20
|
+
end
|
21
|
+
|
22
|
+
should "not have a service handler ns by default" do
|
23
|
+
assert_nil subject.service_handler_ns
|
24
|
+
end
|
25
|
+
|
26
|
+
should "allow setting its service handler ns" do
|
27
|
+
namespace = Factory.string
|
28
|
+
subject.service_handler_ns namespace
|
29
|
+
assert_equal namespace, subject.service_handler_ns
|
30
|
+
end
|
31
|
+
|
32
|
+
should "allow adding routes using `service`" do
|
33
|
+
service_name = Factory.string
|
34
|
+
handler_name = Factory.string
|
35
|
+
subject.service service_name, handler_name
|
36
|
+
|
37
|
+
route = subject.routes.last
|
38
|
+
assert_instance_of Sanford::Route, route
|
39
|
+
assert_equal service_name, route.name
|
40
|
+
assert_equal handler_name, route.handler_class_name
|
41
|
+
end
|
42
|
+
|
43
|
+
should "use its service handler ns when adding routes" do
|
44
|
+
namespace = Factory.string
|
45
|
+
subject.service_handler_ns namespace
|
46
|
+
|
47
|
+
service_name = Factory.string
|
48
|
+
handler_name = Factory.string
|
49
|
+
subject.service service_name, handler_name
|
50
|
+
|
51
|
+
route = subject.routes.last
|
52
|
+
expected = "#{namespace}::#{handler_name}"
|
53
|
+
assert_equal expected, route.handler_class_name
|
54
|
+
end
|
55
|
+
|
56
|
+
should "know its custom inspect" do
|
57
|
+
reference = '0x0%x' % (subject.object_id << 1)
|
58
|
+
expected = "#<#{subject.class}:#{reference} " \
|
59
|
+
"@service_handler_ns=#{subject.service_handler_ns.inspect}>"
|
60
|
+
assert_equal expected, subject.inspect
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|