hatetepe 0.6.0.pre → 0.6.0.pre.1

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.
@@ -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