sanford 0.15.1 → 0.16.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.
@@ -1,12 +1,16 @@
1
1
  require 'assert'
2
2
  require 'sanford/service_handler'
3
3
 
4
+ require 'much-plugin'
4
5
  require 'sanford/template_engine'
5
6
  require 'sanford/template_source'
7
+ require 'sanford/test_runner'
6
8
 
7
9
  module Sanford::ServiceHandler
8
10
 
9
11
  class UnitTests < Assert::Context
12
+ include Sanford::ServiceHandler::TestHelpers
13
+
10
14
  desc "Sanford::ServiceHandler"
11
15
  setup do
12
16
  @handler_class = Class.new{ include Sanford::ServiceHandler }
@@ -23,6 +27,10 @@ module Sanford::ServiceHandler
23
27
  should have_imeths :prepend_before_init, :prepend_after_init
24
28
  should have_imeths :prepend_before_run, :prepend_after_run
25
29
 
30
+ should "use much-plugin" do
31
+ assert_includes MuchPlugin, Sanford::ServiceHandler
32
+ end
33
+
26
34
  should "return an empty array by default using `before_callbacks`" do
27
35
  assert_equal [], subject.before_callbacks
28
36
  end
@@ -136,21 +144,15 @@ module Sanford::ServiceHandler
136
144
  class InitTests < UnitTests
137
145
  desc "when init"
138
146
  setup do
139
- @runner = FakeRunner.new
140
- @handler = TestServiceHandler.new(@runner)
147
+ @runner = test_runner(TestServiceHandler)
148
+ @handler = @runner.handler
141
149
  end
142
150
  subject{ @handler }
143
151
 
144
- should have_imeths :init, :init!, :run, :run!
145
-
146
- should "know its request, params and logger" do
147
- assert_equal @runner.request, subject.public_request
148
- assert_equal @runner.params, subject.public_params
149
- assert_equal @runner.logger, subject.public_logger
150
- end
152
+ should have_imeths :sanford_init, :init!, :sanford_run, :run!
153
+ should have_imeths :sanford_run_callback
151
154
 
152
- should "call `init!` and its before/after init callbacks using `init`" do
153
- subject.init
155
+ should "have called `init!` and its before/after init callbacks" do
154
156
  assert_equal 1, subject.first_before_init_call_order
155
157
  assert_equal 2, subject.second_before_init_call_order
156
158
  assert_equal 3, subject.init_call_order
@@ -158,37 +160,138 @@ module Sanford::ServiceHandler
158
160
  assert_equal 5, subject.second_after_init_call_order
159
161
  end
160
162
 
161
- should "call `run!` and its before/after run callbacks using `run`" do
162
- subject.run
163
- assert_equal 1, subject.first_before_run_call_order
164
- assert_equal 2, subject.second_before_run_call_order
165
- assert_equal 3, subject.run_call_order
166
- assert_equal 4, subject.first_after_run_call_order
167
- assert_equal 5, subject.second_after_run_call_order
163
+ should "not have called `run!` and its before/after run callbacks" do
164
+ assert_nil subject.first_before_run_call_order
165
+ assert_nil subject.second_before_run_call_order
166
+ assert_nil subject.run_call_order
167
+ assert_nil subject.first_after_run_call_order
168
+ assert_nil subject.second_after_run_call_order
168
169
  end
169
170
 
170
- should "have a custom inspect" do
171
- reference = '0x0%x' % (subject.object_id << 1)
172
- expected = "#<#{subject.class}:#{reference} " \
173
- "@request=#{@runner.request.inspect}>"
174
- assert_equal expected, subject.inspect
171
+ should "run its callbacks with `sanford_run_callback`" do
172
+ subject.sanford_run_callback 'before_run'
173
+ assert_equal 6, subject.first_before_run_call_order
174
+ assert_equal 7, subject.second_before_run_call_order
175
175
  end
176
176
 
177
- should "delegate its runner's `render` method" do
178
- path = Factory.file_path
179
- locals = { 'something' => Factory.string }
180
- result = subject.render(path, locals)
181
- assert_equal [path, locals], @runner.render_calls.last
177
+ should "know if it is equal to another service handler" do
178
+ handler = test_handler(TestServiceHandler)
179
+ assert_equal handler, subject
180
+
181
+ handler = test_handler(Class.new{ include Sanford::ServiceHandler })
182
+ assert_not_equal handler, subject
182
183
  end
183
184
 
184
- should "delegate its runner's `halt` method" do
185
- code = Factory.integer
186
- result = subject.halt(code)
187
- assert_equal [code], @runner.halt_calls.last
185
+ end
186
+
187
+ class RunTests < InitTests
188
+ desc "and run"
189
+ setup do
190
+ @handler.sanford_run
188
191
  end
189
192
 
190
- should "raise a not implemented error when `run!` by default" do
191
- assert_raises(NotImplementedError){ @handler_class.new(@runner).run! }
193
+ should "call `run!` and it's callbacks" do
194
+ assert_equal 6, subject.first_before_run_call_order
195
+ assert_equal 7, subject.second_before_run_call_order
196
+ assert_equal 8, subject.run_call_order
197
+ assert_equal 9, subject.first_after_run_call_order
198
+ assert_equal 10, subject.second_after_run_call_order
199
+ end
200
+
201
+ end
202
+
203
+ class PrivateHelpersTests < InitTests
204
+ setup do
205
+ @something = Factory.string
206
+ @args = (Factory.integer(3)+1).times.map{ Factory.string }
207
+ end
208
+
209
+ should "call to the runner for its logger" do
210
+ stub_runner_with_something_for(:logger)
211
+ assert_equal @runner.logger, subject.instance_eval{ logger }
212
+ end
213
+
214
+ should "call to the runner for its request" do
215
+ stub_runner_with_something_for(:request)
216
+ assert_equal @runner.request, subject.instance_eval{ request }
217
+ end
218
+
219
+ should "call to the runner for its params" do
220
+ stub_runner_with_something_for(:params)
221
+ assert_equal @runner.params, subject.instance_eval{ params }
222
+ end
223
+
224
+ should "call to the runner for its status helper" do
225
+ capture_runner_meth_args_for(:status)
226
+ exp_args = @args
227
+ subject.instance_eval{ status(*exp_args) }
228
+
229
+ assert_equal exp_args, @meth_args
230
+ assert_nil @meth_block
231
+ end
232
+
233
+ should "call to the runner for its data helper" do
234
+ capture_runner_meth_args_for(:data)
235
+ exp_args = @args
236
+ subject.instance_eval{ data(*exp_args) }
237
+
238
+ assert_equal exp_args, @meth_args
239
+ assert_nil @meth_block
240
+ end
241
+
242
+ should "call to the runner for its halt helper" do
243
+ capture_runner_meth_args_for(:halt)
244
+ exp_args = @args
245
+ subject.instance_eval{ halt(*exp_args) }
246
+
247
+ assert_equal exp_args, @meth_args
248
+ end
249
+
250
+ should "call to the runner for its render helper" do
251
+ capture_runner_meth_args_for(:render)
252
+ exp_args = @args
253
+ subject.instance_eval{ render(*exp_args) }
254
+
255
+ assert_equal exp_args, @meth_args
256
+ end
257
+
258
+ private
259
+
260
+ def stub_runner_with_something_for(meth)
261
+ Assert.stub(@runner, meth){ @something }
262
+ end
263
+
264
+ def capture_runner_meth_args_for(meth)
265
+ Assert.stub(@runner, meth) do |*args|
266
+ @meth_args = args
267
+ end
268
+ end
269
+
270
+ end
271
+
272
+ class TestHelpersTests < UnitTests
273
+ desc "TestHelpers"
274
+ setup do
275
+ context_class = Class.new{ include Sanford::ServiceHandler::TestHelpers }
276
+ @context = context_class.new
277
+ end
278
+ subject{ @context }
279
+
280
+ should have_imeths :test_runner, :test_handler
281
+
282
+ should "build a test runner for a given handler class" do
283
+ runner = subject.test_runner(@handler_class)
284
+
285
+ assert_kind_of ::Sanford::TestRunner, runner
286
+ assert_equal @handler_class, runner.handler_class
287
+ end
288
+
289
+ should "return an initialized handler instance" do
290
+ handler = subject.test_handler(@handler_class)
291
+ assert_kind_of @handler_class, handler
292
+
293
+ exp = subject.test_runner(@handler_class).handler
294
+ assert_equal exp, handler
192
295
  end
193
296
 
194
297
  end
@@ -202,11 +305,6 @@ module Sanford::ServiceHandler
202
305
  attr_reader :first_after_run_call_order, :second_after_run_call_order
203
306
  attr_reader :init_call_order, :run_call_order
204
307
 
205
- # these methods are made public so they can be tested, they are being tested
206
- # because they are used by classes that mixin this, essentially they are
207
- # "public" to classes that use the mixin
208
- public :render, :halt
209
-
210
308
  before_init{ @first_before_init_call_order = next_call_order }
211
309
  before_init{ @second_before_init_call_order = next_call_order }
212
310
 
@@ -227,38 +325,13 @@ module Sanford::ServiceHandler
227
325
  @run_call_order = next_call_order
228
326
  end
229
327
 
230
- def public_request
231
- request
232
- end
233
-
234
- def public_params
235
- params
236
- end
237
-
238
- def public_logger
239
- logger
240
- end
241
-
242
328
  private
243
329
 
244
330
  def next_call_order
245
331
  @order ||= 0
246
332
  @order += 1
247
333
  end
248
- end
249
-
250
- class FakeRunner
251
- attr_accessor :request, :params, :logger
252
- attr_reader :render_calls, :halt_calls
253
-
254
- def initialize
255
- @request = Factory.string
256
- @params = Factory.string
257
- @logger = Factory.string
258
- end
259
334
 
260
- def render(*args); @render_calls ||= []; @render_calls << args; end
261
- def halt(*args); @halt_calls ||= []; @halt_calls << args; end
262
335
  end
263
336
 
264
337
  end
@@ -7,7 +7,7 @@ class Sanford::TestRunner
7
7
  desc "Sanford::TestRunner"
8
8
  setup do
9
9
  @handler_class = TestServiceHandler
10
- @runner_class = Sanford::TestRunner
10
+ @runner_class = Sanford::TestRunner
11
11
  end
12
12
  subject{ @runner_class }
13
13
 
@@ -22,11 +22,11 @@ class Sanford::TestRunner
22
22
  setup do
23
23
  @params = { Factory.string => Factory.integer }
24
24
  @args = {
25
- :request => Factory.string,
26
- :params => @params,
27
25
  :logger => Factory.string,
28
26
  :router => Factory.string,
29
27
  :template_source => Factory.string,
28
+ :request => Factory.string,
29
+ :params => @params,
30
30
  :custom_value => Factory.integer
31
31
  }
32
32
  @original_args = @args.dup
@@ -35,43 +35,20 @@ class Sanford::TestRunner
35
35
  end
36
36
  subject{ @runner }
37
37
 
38
- should have_readers :response
39
- should have_imeths :run
38
+ should have_imeths :halted?, :run
40
39
 
41
- should "know its standard attributes" do
42
- assert_equal @args[:request], subject.request
43
- assert_equal @params, subject.params
40
+ should "raise an invalid error when passed a non service handler" do
41
+ assert_raises(Sanford::InvalidServiceHandlerError) do
42
+ @runner_class.new(Class.new)
43
+ end
44
+ end
45
+
46
+ should "know its standard args" do
44
47
  assert_equal @args[:logger], subject.logger
45
48
  assert_equal @args[:router], subject.router
46
49
  assert_equal @args[:template_source], subject.template_source
47
- end
48
-
49
- should "write any non-standard args to its handler" do
50
- assert_equal @args[:custom_value], @handler.custom_value
51
- end
52
-
53
- should "not alter the args passed to it" do
54
- assert_equal @original_args, @args
55
- end
56
-
57
- should "not call its service handlers before callbacks" do
58
- assert_nil @handler.before_called
59
- end
60
-
61
- should "call its service handlers init" do
62
- assert_true @handler.init_called
63
- end
64
-
65
- should "not run its service handler" do
66
- assert_false @handler.run_called
67
- end
68
-
69
- should "not call its service handlers after callbacks" do
70
- assert_nil @handler.after_called
71
- end
72
-
73
- should "not have a response by default" do
74
- assert_nil @handler.response
50
+ assert_equal @args[:request], subject.request
51
+ assert_equal @args[:params], subject.params
75
52
  end
76
53
 
77
54
  should "normalize the params passed to it" do
@@ -85,94 +62,55 @@ class Sanford::TestRunner
85
62
  assert_equal exp, runner.params
86
63
  end
87
64
 
88
- should "raise a serialization error if the params can't be serialized" do
65
+ should "complain if the params can't be serialized" do
89
66
  params = { Factory.string => Class.new }
90
67
  assert_raises(BSON::InvalidDocument) do
91
68
  @runner_class.new(@handler_class, :params => params)
92
69
  end
93
70
  end
94
71
 
95
- should "raise an invalid error when passed a non service handler" do
96
- assert_raises(Sanford::InvalidServiceHandlerError) do
97
- @runner_class.new(Class.new)
98
- end
99
- end
100
-
101
- end
102
-
103
- class RunTests < InitTests
104
- desc "and run"
105
- setup do
106
- @response = @runner.run
107
- end
108
- subject{ @response }
109
-
110
- should "know its response" do
111
- assert_equal subject, @runner.response
112
- assert_instance_of Sanford::Protocol::Response, subject
72
+ should "write any non-standard args to its handler" do
73
+ assert_equal @args[:custom_value], subject.handler.custom_value
113
74
  end
114
75
 
115
- should "run its service handler" do
116
- assert_true @runner.handler.run_called
76
+ should "not alter the args passed to it" do
77
+ assert_equal @original_args, @args
117
78
  end
118
79
 
119
- should "not call its service handler's after callbacks" do
120
- assert_nil @runner.handler.after_called
80
+ should "not call its handler's before callbacks" do
81
+ assert_nil @handler.before_called
121
82
  end
122
83
 
123
- end
124
-
125
- class RunWithInvalidResponseTests < InitTests
126
- desc "and run with an invalid response"
127
- setup do
128
- @runner.handler.response = Class.new
84
+ should "call its handler's init" do
85
+ assert_true @handler.init_called
129
86
  end
130
87
 
131
- should "raise a serialization error" do
132
- assert_raises(BSON::InvalidDocument){ subject.run }
88
+ should "not call its handler's run" do
89
+ assert_nil @handler.run_called
133
90
  end
134
91
 
135
- end
136
-
137
- class InitThatHaltsTests < UnitTests
138
- desc "when init with a handler that halts in its init"
139
- setup do
140
- @runner = @runner_class.new(HaltServiceHandler)
92
+ should "not call its handler's after callbacks" do
93
+ assert_nil @handler.after_called
141
94
  end
142
- subject{ @runner }
143
95
 
144
- should "know the response from the init halting" do
145
- assert_instance_of Sanford::Protocol::Response, subject.response
146
- assert_equal subject.handler.response_code, subject.response.code
96
+ should "not be halted by default" do
97
+ assert_false subject.halted?
147
98
  end
148
99
 
149
- end
150
-
151
- class RunWithInitThatHaltsTests < InitThatHaltsTests
152
- desc "is run"
153
- setup do
154
- @response = @runner.run
155
- end
156
- subject{ @response }
157
-
158
- should "not call run on the service handler" do
159
- assert_false @runner.handler.run_called
100
+ should "not call `run` on its handler if halted when run" do
101
+ catch(:halt){ subject.halt }
102
+ assert_true subject.halted?
103
+ subject.run
104
+ assert_nil @handler.run_called
160
105
  end
161
106
 
162
- should "return the response from the init halting" do
163
- assert_instance_of Sanford::Protocol::Response, subject
164
- assert_equal @runner.handler.response_code, subject.code
107
+ should "return its `to_response` value on run" do
108
+ assert_equal subject.to_response, subject.run
165
109
  end
166
110
 
167
- end
168
-
169
- class RunWithInvalidResponseFromInitHaltTests < UnitTests
170
- desc "when init with a handler that halts in its init an invalid response"
171
-
172
- should "raise a serialization error" do
173
- assert_raises(BSON::InvalidDocument) do
174
- @runner_class.new(HaltServiceHandler, :response_data => Class.new)
175
- end
111
+ should "complain if the respose value can't be encoded" do
112
+ subject.data(Class.new)
113
+ assert_raises(BSON::InvalidDocument){ subject.run }
176
114
  end
177
115
 
178
116
  end
@@ -189,13 +127,13 @@ class Sanford::TestRunner
189
127
 
190
128
  def init!
191
129
  @init_called = true
192
- @run_called = false
193
130
  end
194
131
 
195
132
  def run!
196
133
  @run_called = true
197
134
  @response || Factory.boolean
198
135
  end
136
+
199
137
  end
200
138
 
201
139
  class HaltServiceHandler
@@ -214,6 +152,7 @@ class Sanford::TestRunner
214
152
  def run!
215
153
  @run_called = true
216
154
  end
155
+
217
156
  end
218
157
 
219
158
  end
@@ -0,0 +1,185 @@
1
+ require 'assert'
2
+ require 'sanford/worker'
3
+
4
+ require 'dat-tcp/worker'
5
+ require 'much-plugin'
6
+ require 'sanford-protocol/fake_connection'
7
+ require 'sanford/server_data'
8
+ require 'test/support/fake_server_connection'
9
+
10
+ module Sanford::Worker
11
+
12
+ class UnitTests < Assert::Context
13
+ include DatTCP::Worker::TestHelpers
14
+
15
+ desc "Sanford::Worker"
16
+ setup do
17
+ @worker_class = Class.new{ include Sanford::Worker }
18
+ end
19
+ subject{ @worker_class }
20
+
21
+ should "use much-plugin" do
22
+ assert_includes MuchPlugin, Sanford::Worker
23
+ end
24
+
25
+ should "be a dat-tcp worker" do
26
+ assert_includes DatTCP::Worker, subject
27
+ end
28
+
29
+ end
30
+
31
+ class InitTests < UnitTests
32
+ desc "when init"
33
+ setup do
34
+ @socket = Factory.binary
35
+ @server_data = Sanford::ServerData.new
36
+
37
+ @connection = FakeServerConnection.new
38
+ Assert.stub(Connection, :new).with(@socket){ @connection }
39
+
40
+ @ch_spy = nil
41
+ Assert.stub(Sanford::ConnectionHandler, :new) do |*args|
42
+ @ch_spy = ConnectionHandlerSpy.new(*args)
43
+ end
44
+
45
+ @worker_params = {
46
+ :sanford_server_data => @server_data
47
+ }
48
+ @runner = test_runner(@worker_class, :params => @worker_params)
49
+ end
50
+ subject{ @runner }
51
+
52
+ should "build and run a connection handler when it processes a socket" do
53
+ Assert.stub(@server_data, :receives_keep_alive){ false }
54
+ @connection.read_data = Factory.string
55
+ subject.work(@socket)
56
+
57
+ assert_not_nil @ch_spy
58
+ assert_equal @server_data, @ch_spy.server_data
59
+ assert_equal @connection, @ch_spy.connection
60
+ assert_true @ch_spy.run_called
61
+ end
62
+
63
+ should "not run a connection handler when it processes a " \
64
+ "keep-alive connection and its configured to expect them" do
65
+ Assert.stub(@server_data, :receives_keep_alive){ true }
66
+ @connection.read_data = nil # nothing to read makes it a keep-alive
67
+ subject.work(@socket)
68
+
69
+ assert_nil @ch_spy
70
+ end
71
+
72
+ should "run a connection handler when it processes a " \
73
+ "keep-alive connection and its not configured to expect them" do
74
+ Assert.stub(@server_data, :receives_keep_alive){ false }
75
+ @connection.read_data = nil # nothing to read makes it a keep-alive
76
+ subject.work(@socket)
77
+
78
+ assert_not_nil @ch_spy
79
+ assert_equal @server_data, @ch_spy.server_data
80
+ assert_equal @connection, @ch_spy.connection
81
+ assert_true @ch_spy.run_called
82
+ end
83
+
84
+ end
85
+
86
+ class ConnectionTests < UnitTests
87
+ desc "Connection"
88
+ setup do
89
+ fake_socket = Factory.string
90
+ @protocol_conn = Sanford::Protocol::FakeConnection.new(Factory.binary)
91
+ Assert.stub(Sanford::Protocol::Connection, :new).with(fake_socket) do
92
+ @protocol_conn
93
+ end
94
+ @connection = Connection.new(fake_socket)
95
+ end
96
+ subject{ @connection }
97
+
98
+ should have_imeths :read_data, :write_data, :peek_data
99
+ should have_imeths :close_write
100
+
101
+ should "default its timeout" do
102
+ assert_equal 1.0, subject.timeout
103
+ end
104
+
105
+ should "allowing reading from the protocol connection" do
106
+ result = subject.read_data
107
+ assert_equal @protocol_conn.read_data, result
108
+ assert_equal @protocol_conn.read_timeout, subject.timeout
109
+ end
110
+
111
+ should "allowing writing to the protocol connection" do
112
+ data = Factory.binary
113
+ subject.write_data(data)
114
+ assert_equal @protocol_conn.write_data, data
115
+ end
116
+
117
+ should "allowing peeking from the protocol connection" do
118
+ result = subject.peek_data
119
+ assert_equal @protocol_conn.peek_data, result
120
+ assert_equal @protocol_conn.peek_timeout, subject.timeout
121
+ end
122
+
123
+ should "allow closing the write stream on the protocol connection" do
124
+ assert_false @protocol_conn.closed_write
125
+ subject.close_write
126
+ assert_true @protocol_conn.closed_write
127
+ end
128
+
129
+ end
130
+
131
+ class TCPCorkTests < UnitTests
132
+ desc "TCPCork"
133
+ subject{ TCPCork }
134
+
135
+ should have_imeths :apply, :remove
136
+
137
+ end
138
+
139
+ class TestHelpersTests < UnitTests
140
+ desc "TestHelpers"
141
+ setup do
142
+ @context_class = Class.new{ include TestHelpers }
143
+ @context = @context_class.new
144
+ end
145
+ subject{ @context }
146
+
147
+ should have_imeths :test_runner
148
+
149
+ should "mixin dat-tcp's worker test helpers" do
150
+ assert_includes DatTCP::Worker::TestHelpers, @context_class
151
+ end
152
+
153
+ should "super worker params needed to run a sanford worker" do
154
+ runner = @context.test_runner(@worker_class)
155
+ worker_params = runner.dwp_runner.worker_params
156
+
157
+ assert_instance_of Sanford::ServerData, worker_params[:sanford_server_data]
158
+ end
159
+
160
+ should "allow providing custom worker params for running a sanford worker" do
161
+ @params = {
162
+ :sanford_server_data => Factory.string,
163
+ }
164
+ runner = @context.test_runner(@worker_class, :params => @params)
165
+
166
+ assert_equal @params, runner.dwp_runner.worker_params
167
+ end
168
+
169
+ end
170
+
171
+ class ConnectionHandlerSpy
172
+ attr_reader :server_data, :connection, :run_called
173
+
174
+ def initialize(server_data, connection)
175
+ @server_data = server_data
176
+ @connection = connection
177
+ @run_called = false
178
+ end
179
+
180
+ def run
181
+ @run_called = true
182
+ end
183
+ end
184
+
185
+ end