sanford 0.10.1 → 0.11.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.
- 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
|