hatetepe 0.4.1 → 0.5.0.pre

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