hatetepe 0.6.0.pre → 0.6.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,11 +11,11 @@ describe 'Smoke test' do
11
11
  it 'exchanges request and response' do
12
12
  expect(response.status).to be(200)
13
13
  expect(response.headers).to include('Content-Length' => '1')
14
- expect(response.body).to eq('/')
14
+ expect(response.body.to_s).to eq('/')
15
15
 
16
16
  expect(request.http_method).to be(:get)
17
17
  expect(request.uri).to eq('/')
18
18
  expect(request.headers).to include('Content-Length' => '0')
19
- expect(request.body).to eq('')
19
+ expect(request.body.to_s).to eq('')
20
20
  end
21
21
  end
@@ -5,25 +5,26 @@ require 'spec_helper'
5
5
  describe 'Request body streaming' do
6
6
  include_context :server_client_pair
7
7
 
8
- let(:bodies) { [] }
9
8
  let(:chunks) { [] }
10
9
 
11
10
  before do
12
11
  client.perform(request)
13
12
  tick(2)
14
- intercepted_requests[0].finished.on_progress do |chunk|
15
- bodies << intercepted_requests[0].body.dup
16
- chunks << chunk
17
- end
13
+ Fiber.new do
14
+ intercepted_requests[0].body.each do |chunk|
15
+ chunks << chunk
16
+ end
17
+ end.resume
18
18
  end
19
19
 
20
- let(:request) { default_request }
20
+ let(:request) { open_request }
21
21
 
22
22
  subject! do
23
23
  %w[foo bar baz].each do |chunk|
24
- request.finished.progress(chunk)
24
+ request.body.closed.progress(chunk)
25
25
  tick
26
26
  end
27
+ request.close
27
28
  tick
28
29
  end
29
30
 
@@ -31,7 +32,6 @@ describe 'Request body streaming' do
31
32
  expect(intercepted_requests[0].headers)
32
33
  .to include('Transfer-Encoding' => 'chunked')
33
34
 
34
- expect(bodies).to eq(%w[foo foobar foobarbaz])
35
35
  expect(chunks).to eq(%w[foo bar baz])
36
36
  end
37
37
  end
@@ -39,7 +39,6 @@ end
39
39
  describe 'Response body streaming' do
40
40
  include_context :server_client_pair
41
41
 
42
- let(:bodies) { [] }
43
42
  let(:chunks) { [] }
44
43
 
45
44
  let(:response) { client.request(:get, '/streaming') }
@@ -47,15 +46,12 @@ describe 'Response body streaming' do
47
46
  subject! { response }
48
47
 
49
48
  before do
50
- response.finished.on_progress do |chunk|
51
- bodies << response.body.dup
49
+ response.body.each do |chunk|
52
50
  chunks << chunk
53
51
  end
54
- response.finished.sync
55
52
  end
56
53
 
57
54
  it 'progressively receives the body' do
58
- expect(bodies).to eq(%w[foo foobar foobarbaz])
59
55
  expect(chunks).to eq(%w[foo bar baz])
60
56
  end
61
57
  end
@@ -4,28 +4,24 @@ class SpecHandler
4
4
  def initialize(config, server, connection)
5
5
  end
6
6
 
7
- def serve(request)
8
- response = response_for(request)
9
- request.served.fulfill(response)
7
+ def serve(request, served)
8
+ served.fulfill(response_for(request))
10
9
  end
11
10
 
12
11
  private
13
12
 
14
13
  def response_for(request)
15
14
  case request.uri
16
- when '/' then root_response.tap(&fulfill)
17
- when '/sleep' then sleep_response.tap(&fulfill)
18
- when '/close' then close_response.tap(&fulfill)
15
+ when '/sleep' then sleep_response
16
+ when '/close' then close_response
19
17
  when '/streaming' then streaming_response
18
+ else echo_response(request)
20
19
  end
21
20
  end
22
21
 
23
- def fulfill
24
- proc { |response| response.finished.fulfill }
25
- end
26
-
27
- def root_response
28
- Hatetepe::Response.new(200, { 'Content-Type' => 'text/plain' }, '/')
22
+ def echo_response(request)
23
+ Hatetepe::Response.new(200, { 'Content-Type' => 'text/plain' },
24
+ request.uri)
29
25
  end
30
26
 
31
27
  def sleep_response
@@ -41,14 +37,14 @@ class SpecHandler
41
37
  end
42
38
 
43
39
  def streaming_response
44
- response = Hatetepe::Response.new(200, 'Content-Type' => 'text/plain')
40
+ response = Hatetepe::Response.new(200, { 'Content-Type' => 'text/plain' },
41
+ Hatetepe::Body.new)
45
42
  SpecHelper.defer do
46
43
  %w[foo bar baz].each do |chunk|
47
44
  SpecHelper.tick(2)
48
- response.body << chunk
49
- response.finished.progress(chunk)
45
+ response.body.closed.progress(chunk)
50
46
  end
51
- response.finished.fulfill
47
+ response.close
52
48
  end
53
49
  response
54
50
  end
@@ -24,20 +24,20 @@ module SpecHelper
24
24
  end
25
25
  module_function :defer
26
26
 
27
- def default_request(http_method = :get, uri = '/', headers = {})
28
- Hatetepe::Request.new(http_method, uri, headers)
27
+ def open_request(http_method = :get, uri = '/', headers = {})
28
+ Hatetepe::Request.new(http_method, uri, headers, Hatetepe::Body.new)
29
29
  end
30
30
 
31
- def finished_request(*args)
32
- default_request(*args).tap { |request| request.finished.fulfill }
31
+ def closed_request(*args)
32
+ open_request(*args).tap(&:close)
33
33
  end
34
34
 
35
- def default_response(status = 200, headers = {})
36
- Hatetepe::Response.new(status, headers)
35
+ def open_response(status = 200, headers = {})
36
+ Hatetepe::Response.new(status, headers, Hatetepe::Body.new)
37
37
  end
38
38
 
39
- def finished_response(*args)
40
- default_response(*args).tap { |response| response.finished.fulfill }
39
+ def closed_response(*args)
40
+ open_response(*args).tap(&:close)
41
41
  end
42
42
 
43
43
  def localhost
@@ -15,7 +15,7 @@ describe Hatetepe::Client do
15
15
  close: nil)
16
16
  end
17
17
  let(:handler_class) { double('handler_class', new: handler) }
18
- let(:handler) { double('handler', post_init: nil, receive: nil) }
18
+ let(:handler) { double('handler', setup: nil, receive: nil) }
19
19
 
20
20
  before do
21
21
  allow(EM).to receive(:connect) { connection }
@@ -39,28 +39,27 @@ describe Hatetepe::Client do
39
39
  specify do
40
40
  expect(handler_class).to have_received(:new)
41
41
  .with(config, subject, connection)
42
- expect(handler).to have_received(:post_init)
42
+ expect(handler).to have_received(:setup)
43
43
  end
44
44
  end
45
45
 
46
46
  describe '#request' do
47
47
  let(:request) do
48
- double('request', finished: double('finished', fulfill: nil),
49
- served: double('served', sync: response))
48
+ double('request', body: double(closed: double('closed', fulfill: nil)))
50
49
  end
51
50
  let(:response) { double('response') }
51
+ let(:served) { double('served', sync: response) }
52
52
 
53
53
  before do
54
- allow(Hatetepe::Request).to receive(:new) { request }
55
- allow(client).to receive(:perform)
54
+ allow(Hatetepe::Request).to receive(:new) { request }
55
+ allow(client).to receive(:perform) { served }
56
56
  end
57
57
 
58
58
  subject! { client.request(:head, '/wat') }
59
59
 
60
60
  specify do
61
- expect(Hatetepe::Request).to have_received(:new).with(:head, '/wat')
62
- expect(request.finished).to have_received(:fulfill)
63
- expect(client).to have_received(:perform).with(request)
61
+ expect(Hatetepe::Request).to have_received(:new).with(:head, '/wat')
62
+ expect(client).to have_received(:perform).with(request)
64
63
 
65
64
  expect(subject).to be(response)
66
65
  end
@@ -95,17 +94,17 @@ describe Hatetepe::Client do
95
94
  end
96
95
 
97
96
  describe '#receive' do
98
- let(:request) { default_request }
99
- let(:response) { default_response }
97
+ let(:request) { open_request }
98
+ let(:response) { open_response }
100
99
 
101
100
  describe 'with outstanding request' do
102
- before { client.perform(request) }
101
+ let!(:served) { client.perform(request) }
103
102
 
104
103
  subject! { client.receive(response) }
105
104
 
106
105
  it 'correlates response with request, and notifies handlers' do
107
- expect(request.served).to be_fulfilled
108
- expect(request.served.value).to be(response)
106
+ expect(served).to be_fulfilled
107
+ expect(served.value).to be(response)
109
108
 
110
109
  expect(handler).to have_received(:receive).with(request, response)
111
110
  end
@@ -121,8 +120,8 @@ describe Hatetepe::Client do
121
120
 
122
121
  [:fulfill, :reject].each do |action|
123
122
  describe "after #{action}ed response" do
124
- let(:request) { WeakRef.new(finished_request) }
125
- let(:response) { WeakRef.new(default_response) }
123
+ let(:request) { WeakRef.new(closed_request) }
124
+ let(:response) { WeakRef.new(open_response) }
126
125
 
127
126
  before do
128
127
  client.perform(request.__getobj__)
@@ -148,23 +147,25 @@ describe Hatetepe::Client do
148
147
  end
149
148
 
150
149
  describe '#teardown' do
151
- let(:requests) { [finished_request, finished_request] }
152
- let(:responses) { [default_response] }
150
+ let(:requests) { [closed_request, closed_request] }
151
+ let(:responses) { [open_response] }
153
152
  let(:reason) { double }
154
153
 
154
+ let!(:served) do
155
+ requests.map { |request| client.perform(request) }
156
+ end
157
+
155
158
  before do
156
- client.perform(requests[0])
157
- client.perform(requests[1])
158
159
  client.receive(responses[0])
159
160
  end
160
161
 
161
162
  subject! { client.teardown(reason) }
162
163
 
163
164
  it 'rejects outstanding requests and responses' do
164
- expect(responses[0].finished).to be_rejected
165
- expect(responses[0].finished.reason).to be(reason)
166
- expect(requests[1].served).to be_rejected
167
- expect(requests[1].served.reason).to be(reason)
165
+ expect(responses[0].body.closed).to be_rejected
166
+ expect(responses[0].body.closed.reason).to be(reason)
167
+ expect(served[1]).to be_rejected
168
+ expect(served[1].reason).to be(reason)
168
169
  end
169
170
  end
170
171
  end
@@ -7,7 +7,7 @@ describe Hatetepe::Connection::EventMachine do
7
7
  let(:callback) { double('callback', call: nil) }
8
8
  let(:parser) { double('parser', :<< => nil) }
9
9
  let(:serializer) { double('serializer', serialize: nil) }
10
- let(:message) { default_request }
10
+ let(:message) { open_request }
11
11
 
12
12
  before do
13
13
  allow(connection).to receive(:close_connection_after_writing)
@@ -17,8 +17,8 @@ describe Hatetepe::Connection::EventMachine do
17
17
 
18
18
  connection.instance_variable_set(:@signature, 123)
19
19
 
20
- # initialize separately, EM::Connection overloads .new
21
- # this smell tells us that we should decouple from EM::Connection
20
+ # XXX: initialize separately, EM::Connection overloads .new
21
+ # this smell tells us that we should decouple from EM::Connection
22
22
  connection.send(:initialize, callback)
23
23
  end
24
24
 
@@ -120,14 +120,15 @@ describe Hatetepe::Connection::EventMachine do
120
120
  end
121
121
 
122
122
  subject! do
123
- message.finished.on_progress { |chunk| progress << chunk }
123
+ message.body.closed.on_progress { |chunk| progress << chunk }
124
124
  connection.on_body(chunks[0])
125
125
  connection.on_body(chunks[1])
126
+ message.close
126
127
  end
127
128
 
128
129
  it 'passes chunk to message body' do
129
- expect(message.body).to eq(chunks.join)
130
- expect(progress).to eq(chunks)
130
+ expect(message.body.to_s).to eq(chunks.join)
131
+ expect(progress).to eq(chunks)
131
132
  end
132
133
  end
133
134
 
@@ -139,8 +140,8 @@ describe Hatetepe::Connection::EventMachine do
139
140
 
140
141
  subject! { connection.on_message_complete }
141
142
 
142
- it 'fulfills the promise' do
143
- expect(message.finished).to be_fulfilled
143
+ it 'closes the body' do
144
+ expect(message.body.closed).to be_fulfilled
144
145
  end
145
146
  end
146
147
  end
@@ -5,23 +5,23 @@ require 'spec_helper'
5
5
  describe Hatetepe::Request do
6
6
  describe '#initialize' do
7
7
  subject do
8
- Hatetepe::Request.new(:get, '/', { 'Key' => 'value' }, 'hello').freeze
8
+ Hatetepe::Request.new(:get, '/a?b=c',
9
+ { 'Key' => 'value' }, 'hello').freeze
9
10
  end
10
11
 
11
12
  its(:http_method) { should be(:get) }
12
- its(:uri) { should eq('/') }
13
+ its(:uri) { should eq('/a?b=c') }
13
14
  its(:headers) { should eq('Key' => 'value') }
14
- its(:body) { should eq('hello') }
15
15
 
16
- its(:finished) { should be_a(Hatetepe::Promise) }
17
- its(:served) { should be_a(Hatetepe::Promise) }
16
+ specify { expect(subject.body.read).to eq('hello') }
18
17
 
19
18
  describe 'defaults' do
20
19
  subject { Hatetepe::Request.new(:get, '/') }
21
20
 
22
21
  its(:headers) { should eq({}) }
23
- its(:body) { should eq('') }
24
22
  its(:http_version) { should eq(1.1) }
23
+
24
+ specify { expect(subject.body.read).to be_empty }
25
25
  end
26
26
  end
27
27
 
@@ -10,9 +10,8 @@ describe Hatetepe::Response do
10
10
 
11
11
  its(:status) { should be(200) }
12
12
  its(:headers) { should eq('Key' => 'value') }
13
- its(:body) { should eq('hello') }
14
13
 
15
- its(:finished) { should be_a(Hatetepe::Promise) }
14
+ specify { expect(subject.body.read).to eq('hello') }
16
15
 
17
16
  its(:status_name) { should eq('OK') }
18
17
 
@@ -20,8 +19,9 @@ describe Hatetepe::Response do
20
19
  subject { Hatetepe::Response.new(200) }
21
20
 
22
21
  its(:headers) { should eq({}) }
23
- its(:body) { should eq('') }
24
22
  its(:http_version) { should eq(1.1) }
23
+
24
+ specify { expect(subject.body.read).to be_empty }
25
25
  end
26
26
 
27
27
  describe 'unknown status' do
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Hatetepe::Server::KeepAlive do
6
+ let(:config) { double('config') }
7
+ let(:server) { double('server') }
8
+ let(:connection) { double('connection') }
9
+
10
+ let(:object) { described_class.new(config, server, connection) }
11
+ let(:request) do
12
+ double('request', http_version: http_version,
13
+ headers: { 'Connection' => header })
14
+ end
15
+ let(:served) { double('served', value: response) }
16
+ let(:response) { double('response', headers: { 'Connection' => header }) }
17
+
18
+ describe '#close_connection?' do
19
+ before { object.serve(request, served) }
20
+
21
+ let(:subject) { object.send(:close_connection?, request) }
22
+
23
+ describe 'with HTTP/1.0 request' do
24
+ let(:http_version) { 1.0 }
25
+
26
+ describe 'and no header' do
27
+ let(:header) { nil }
28
+
29
+ it { should be(true) }
30
+ end
31
+
32
+ describe 'and Connection: close' do
33
+ let(:header) { 'close' }
34
+
35
+ it { should be(true) }
36
+ end
37
+
38
+ describe 'and Connection: keep-alive' do
39
+ let(:header) { 'keep-alive' }
40
+
41
+ it { should be(false) }
42
+ end
43
+ end
44
+
45
+ describe 'with HTTP/1.1 request' do
46
+ let(:http_version) { 1.1 }
47
+
48
+ describe 'and no header' do
49
+ let(:header) { nil }
50
+
51
+ it { should be(false) }
52
+ end
53
+
54
+ describe 'and Connection: close' do
55
+ let(:header) { 'close' }
56
+
57
+ it { should be(true) }
58
+ end
59
+
60
+ describe 'and Connection: keep-alive' do
61
+ let(:header) { 'keep-alive' }
62
+
63
+ it { should be(false) }
64
+ end
65
+ end
66
+ end
67
+ end