hatetepe 0.4.1 → 0.5.0.pre

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,380 +1,85 @@
1
1
  require "spec_helper"
2
2
  require "hatetepe/client"
3
3
 
4
- describe Hatetepe::Client do
5
- let(:client) do
6
- Hatetepe::Client.allocate.tap {|c| c.send :initialize, config }
7
- end
8
- let(:config) { stub "config" }
9
-
10
- let(:uri) { "http://example.net:8080/foo" }
11
- let(:parsed_uri) { URI.parse uri }
12
- let(:request) { Hatetepe::Request.new *request_as_array }
13
- let(:request_as_array) { ["GET", "/foo", {"Host" => "example.net:8080"}, [], "1.1"] }
14
- let(:headers) { {} }
15
- let(:body) { stub "body" }
16
- let(:response) { Hatetepe::Response.new 200 }
17
-
18
- it "inherits from Hatetepe::Connection" do
19
- client.should be_a(Hatetepe::Connection)
20
- end
21
-
22
- describe "#initialize(config)" do
23
- it "sets the config" do
24
- client.config.should equal(config)
25
- end
26
-
27
- it "creates the builder and parser" do
28
- client.parser.should be_a(Hatetepe::Parser)
29
- client.builder.should be_a(Hatetepe::Builder)
30
- end
31
-
32
- it "creates the requests list" do
33
- client.requests.should be_an(Array)
34
- client.requests.should be_empty
35
- end
36
-
37
- it "creates the lists of requests pending transmission or response" do
38
- client.pending_transmission.should be_a(Hash)
39
- client.pending_transmission.should be_empty
40
- client.pending_response.should be_a(Hash)
41
- client.pending_response.should be_empty
42
- end
43
-
44
- it "builds the app" do
45
- client.app.should be_a(Hatetepe::Client::KeepAlive)
46
- client.app.app.should be_a(Hatetepe::Client::Pipeline)
47
- client.app.app.app.should == client.method(:send_request)
48
- end
49
- end
50
-
51
- describe "#post_init" do
52
- it "wires the builder and parser" do
53
- client.post_init
54
- client.builder.on_write[0].should == client.method(:send_data)
55
- client.parser.on_response[0].should == client.method(:receive_response)
4
+ describe Hatetepe::Client, "(public API)" do
5
+ describe ".start"
6
+
7
+ describe "#stop"
8
+
9
+ describe "#stop!"
10
+
11
+ describe "#wait"
12
+
13
+ describe ".request"
14
+
15
+ describe "#request"
16
+
17
+ describe "#<<" do
18
+ let :config do
19
+ {
20
+ :host => "127.0.0.1",
21
+ :port => 4242
22
+ }
56
23
  end
57
-
58
- it "enables processing" do
24
+
25
+ let :subject do
26
+ client = Object.new.extend(Hatetepe::Client)
27
+ client.stub(:send_data)
28
+ client.stub(:comm_inactivity_timeout=)
29
+ client.stub(:pending_connect_timeout=)
30
+ client.send(:initialize, config)
59
31
  client.post_init
60
- client.processing_enabled.should be_true
61
- end
62
- end
63
-
64
- describe "#receive_data(data)" do
65
- let(:data) { stub "data" }
66
-
67
- it "feeds the data into the parser" do
68
- client.parser.should_receive(:<<).with data
69
- client.receive_data data
70
- end
71
-
72
- let(:error) { StandardError.new "alarm! eindringlinge! alarm!" }
73
-
74
- it "stops the client if it catches an error" do
75
- client.parser.should_receive(:<<).and_raise error
76
- client.should_receive :close_connection
77
- proc { client.receive_data data }.should raise_error(error)
78
- end
79
- end
80
-
81
- describe "#send_request(request)" do
82
- let(:entry) { stub "entry" }
83
-
84
- before do
85
- client.pending_transmission[request.object_id] = entry
86
- client.builder.stub :request
87
- entry.stub :succeed
88
- EM::Synchrony.stub :sync
89
- end
90
-
91
- it "feeds the request into the builder" do
92
- client.builder.should_receive(:request).with request_as_array
93
- client.send_request request
94
- end
95
-
96
- it "succeeds the request's entry in the pending transmission list" do
97
- entry.should_receive :succeed
98
- client.send_request request
99
- end
100
-
101
- it "adds the request to the pending response list and waits" do
102
- EM::Synchrony.should_receive(:sync) do |syncee|
103
- syncee.should respond_to(:succeed)
104
- client.pending_response[request.object_id].should equal(syncee)
105
- end
106
- client.send_request request
107
- end
108
-
109
- it "returns the waiting result" do
110
- EM::Synchrony.should_receive(:sync).and_return response
111
- client.send_request(request).should equal(response)
112
- end
113
-
114
- it "makes sure the request gets removed from the pending response list" do
115
- EM::Synchrony.should_receive(:sync).and_raise StandardError
116
- client.send_request request rescue nil
117
- client.pending_response.should be_empty
118
- end
119
- end
120
-
121
- describe "#receive_response(response)" do
122
- let(:requests) {
123
- [
124
- stub("request_with_response", :response => stub("response")),
125
- request,
126
- stub("another_request", :response => nil)
127
- ]
128
- }
129
- let(:id) { requests[1].object_id }
130
-
131
- before do
132
- client.stub :requests => requests
133
- client.pending_response[id] = stub("entry", :succeed => nil)
134
- end
135
-
136
- it "succeeds the pending response list entry of the first request without a response" do
137
- client.pending_response[id].should_receive(:succeed).with response
138
- client.receive_response response
139
- end
140
-
141
- it "associates the response with the corresponding request" do
142
- client.receive_response response
143
- request.response.should equal(response)
144
- end
145
- end
146
-
147
- describe "#<<(request)" do
148
- let(:fiber) { stub "fiber", :resume => nil }
149
- let(:app) { stub "app", :call => response }
150
-
151
- before do
152
- client.processing_enabled = true
153
- client.stub :app => app
154
- Fiber.stub(:new) {|blk| blk.call; fiber }
155
- end
156
-
157
- it "sets a Host header if none is set" do
158
- app.should_receive :call do |req|
159
- req.headers["Host"].should == "example.net:8080"
160
- end
161
- client << request
162
- end
163
-
164
- it "sets the request's connection" do
165
- request.should_receive(:connection=).with client
166
- client << request
167
- end
168
-
169
- it "adds the request to the requests list" do
170
- app.should_receive :call do
171
- client.requests[-1].should equal(request)
172
- end
173
- client << request
174
- client.requests.should be_empty
175
- end
176
-
177
- it "fails and ignores the request if processing is disabled" do
178
- client.processing_enabled = false
179
- request.should_receive :fail
180
- app.should_not_receive :call
181
-
182
- client << request
183
- request.connection.should equal(client)
184
- end
185
-
186
- it "adds the request to the pending transmission list" do
187
- app.should_receive :call do |req|
188
- client.pending_transmission[req.object_id].should respond_to(:succeed)
189
- end
190
- client << request
191
- end
192
-
193
- it "calls the app" do
194
- app.should_receive(:call).with request
195
- client << request
32
+ client
196
33
  end
197
-
198
- it "sets the response" do
199
- request.should_receive(:response=).with response
200
- client << request
201
- end
202
-
203
- it "succeeds the request if the response status indicates success" do
204
- request.should_receive(:succeed).with response
205
- client << request
206
- end
207
-
208
- it "fails the request if the response status indicates failure" do
209
- response.status = 403
210
- request.should_receive(:fail).with response
211
- client << request
212
- end
213
-
214
- it "fails the request if no response has been received" do
215
- app.stub :call => nil
216
- request.should_receive(:fail).with nil
217
- client << request
218
- end
219
-
220
- it "makes sure the request gets removed from the pending transmission list" do
221
- app.should_receive(:call).and_raise StandardError
222
- client << request rescue nil
223
- client.pending_transmission.should be_empty
224
- end
225
- end
226
-
227
- describe "#request(verb, uri, headers, body)" do
228
- before do
229
- EM::Synchrony.stub :sync
230
- client.stub :<<
231
- end
232
-
233
- it "sets the User-Agent header" do
234
- client.should_receive :<< do |request|
235
- request.headers["User-Agent"].should == "hatetepe/#{Hatetepe::VERSION}"
236
- end
237
- client.request :get, uri
34
+
35
+ let :request do
36
+ Hatetepe::Request.new :head, "/test"
238
37
  end
239
-
240
- let(:user_agent) { stub "user-agent" }
241
-
242
- it "doesn't override an existing User-Agent header" do
243
- client.should_receive :<< do |request|
244
- request.headers["User-Agent"].should equal(user_agent)
38
+
39
+ it "calls the app in a Fiber" do
40
+ fiber = Fiber.current
41
+ subject.app.should_receive :call do
42
+ Fiber.current.should_not equal(fiber)
245
43
  end
246
- client.request :get, uri, "User-Agent" => user_agent
44
+
45
+ subject << request
247
46
  end
248
47
 
249
- it "passes the body through #encode_body"
48
+ it "fails the request if the response is a failure" do
49
+ subject.app.stub :call => Hatetepe::Response.new(400)
50
+ request.should_receive(:fail).with(subject.app.call)
250
51
 
251
- it "doesn't close the body" do
252
- body.should_not_receive :close_write
253
- client.request :get, uri, {}, body
254
- end
255
-
256
- it "passes the request to #<<" do
257
- client.should_receive :<< do |request|
258
- request.verb.should == "GET"
259
- request.uri.should == uri
260
- request.headers.should == headers
261
- request.body.should == [body]
262
- end
263
- client.request :get, uri, headers, body
264
- end
265
-
266
- it "waits until the requests succeeds" do
267
- EM::Synchrony.should_receive(:sync).with kind_of(Hatetepe::Request)
268
- client.request :get, uri
269
- end
270
-
271
- it "closes the response body if the request's method was HEAD" do
272
- Hatetepe::Request.any_instance.stub :response => response
273
- response.body.should_receive :close_write
274
- client.request :head, uri
275
- end
276
-
277
- it "returns the response" do
278
- Hatetepe::Request.any_instance.stub :response => response
279
- client.request(:get, uri).should equal(response)
280
- end
281
- end
282
-
283
- describe "#stop" do
284
- before do
285
- response.stub :body => stub("body")
286
- client.stub :requests => [request,
287
- stub("another_request", :response => response)]
288
- client.stub :close_connection
289
- end
290
-
291
- it "waits for the last request to complete and then stops" do
292
- EM::Synchrony.should_receive(:sync).with(client.requests.last) { response }
293
- EM::Synchrony.should_receive(:sync).with response.body
294
- client.should_receive :close_connection
295
- client.stop
296
- end
297
- end
298
-
299
- describe "#wrap_body(body)" do
300
- let(:body) { stub "body" }
301
-
302
- it "doesn't modify a body that responds to #each" do
303
- body.stub :each
304
- client.wrap_body(body).should equal(body)
52
+ subject << request
305
53
  end
306
-
307
- it "makes a body that responds to #read enumerable" do
308
- body.stub :read => stub("#read")
309
- client.wrap_body(body).should == [body.read]
310
- end
311
-
312
- it "makes other bodies enumerable" do
313
- client.wrap_body(body).should == [body]
314
- end
315
-
316
- it "makes an empty body enumerable" do
317
- client.wrap_body(nil).should == []
318
- end
319
- end
320
54
 
321
- describe "#encode_body(headers, body)" do
322
- it ""
323
- end
324
-
325
- describe ".start(config)" do
326
- let(:config) { {:host => "0.0.0.0", :port => 1234} }
327
- let(:client) { stub "client" }
328
-
329
- it "starts an EventMachine connection and returns it" do
330
- EM.should_receive(:connect).with(config[:host], config[:port],
331
- Hatetepe::Client, config) { client }
332
- Hatetepe::Client.start(config).should equal(client)
333
- end
334
- end
335
-
336
- describe ".request(verb, uri, headers, body)" do
337
- let(:client) { stub "client" }
338
-
339
- before do
340
- Hatetepe::Client.stub :start => client
341
- client.stub :request => response, :stop => nil
342
- end
343
-
344
- it "starts a client" do
345
- Hatetepe::Client.should_receive(:start).with :host => parsed_uri.host,
346
- :port => parsed_uri.port
347
- Hatetepe::Client.request :get, uri
348
- end
349
-
350
- it "feeds the request into the client and returns the response" do
351
- client.should_receive(:request).with(:get, parsed_uri.request_uri,
352
- headers, body) { response }
353
- Hatetepe::Client.request(:get, uri, headers, body).should equal(response)
55
+ it "fails the request if there is no response (yet)" do
56
+ subject.app.stub :call => nil
57
+ request.should_receive(:fail).with(nil)
58
+
59
+ subject << request
354
60
  end
355
-
356
- it "stops the client when the response has finished" do
357
- client.should_receive :stop
358
- Hatetepe::Client.request :get, uri
61
+
62
+ it "succeeds the request if the response is a success" do
63
+ subject.app.stub :call => Hatetepe::Response.new(303)
64
+ request.should_receive(:succeed).with(subject.app.call)
65
+
66
+ subject << request
359
67
  end
360
68
  end
361
-
362
- [:get, :head, :post, :put, :delete,
363
- :options, :trace, :connect].each do |verb|
364
- describe "##{verb}(uri, headers, body)" do
365
- it "delegates to #request" do
366
- client.should_receive(:request).with(verb, uri, headers, body) { response }
367
- client.send(verb, uri, headers, body).should equal(response)
368
- end
369
- end
370
-
371
- describe ".#{verb}(uri, headers, body)" do
372
- let(:client) { Hatetepe::Client }
373
-
374
- it "delegates to .request" do
375
- client.should_receive(:request).with(verb, uri, headers, body) { response }
376
- client.send(verb, uri, headers, body).should equal(response)
377
- end
378
- end
379
- end
69
+ end
70
+
71
+ describe Hatetepe::Client, "EventMachine API" do
72
+ describe "#initialize"
73
+
74
+ describe "#post_init"
75
+
76
+ describe "#receive_data"
77
+
78
+ describe "#unbind"
79
+ end
80
+
81
+ describe Hatetepe::Client, "private API" do
82
+ describe "#send_request"
83
+
84
+ describe "#receive_response"
380
85
  end
@@ -2,7 +2,9 @@ require "spec_helper"
2
2
  require "hatetepe/connection"
3
3
 
4
4
  describe Hatetepe::Connection do
5
- let(:conn) { Hatetepe::Connection.allocate }
5
+ let :conn do
6
+ Object.new.extend Hatetepe::Connection
7
+ end
6
8
 
7
9
  let(:peername) { "\x02\x00\x86\xF6\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" }
8
10
  let(:address) { "127.0.0.1" }
@@ -10,10 +12,6 @@ describe Hatetepe::Connection do
10
12
 
11
13
  before { conn.stub :get_peername => peername }
12
14
 
13
- it "inherits from EM::Connection" do
14
- conn.should be_an(EM::Connection)
15
- end
16
-
17
15
  describe "#remote_address" do
18
16
  it "returns the remote peer's address" do
19
17
  conn.remote_address.should == address
@@ -49,14 +47,14 @@ describe Hatetepe::Connection do
49
47
 
50
48
  describe "#unbind" do
51
49
  it "sets the closed-by-remote flag" do
52
- conn.unbind
50
+ conn.unbind(nil)
53
51
  conn.should be_closed
54
52
  conn.should be_closed_by_remote
55
53
  end
56
54
 
57
55
  it "doesn't overwrite an existing closed-by flag" do
58
56
  conn.stub :closed? => true
59
- conn.unbind
57
+ conn.unbind(nil)
60
58
  conn.should be_closed
61
59
  conn.should_not be_closed_by_remote
62
60
  end