sanford 0.15.1 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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