|
1 | 1 | require "webmachine/spec/test_resource" |
2 | 2 | require "net/http" |
3 | 3 |
|
| 4 | +ADDRESS = "127.0.0.1" |
| 5 | + |
4 | 6 | shared_examples_for :adapter_lint do |
5 | | - attr_accessor :client |
| 7 | + attr_reader :client |
| 8 | + |
| 9 | + class TestApplicationNotResponsive < Timeout::Error; end |
6 | 10 |
|
7 | | - let(:address) { "127.0.0.1" } |
8 | | - let(:port) { s = TCPServer.new(address, 0); p = s.addr[1]; s.close; p } |
| 11 | + def find_free_port |
| 12 | + temp_server = TCPServer.new(ADDRESS, 0) |
| 13 | + port = temp_server.addr[1] |
| 14 | + temp_server.close # only frees Ruby resource, socket is in TIME_WAIT at OS level |
| 15 | + # so we can't have our adapter use it too quickly |
9 | 16 |
|
10 | | - let(:application) do |
11 | | - application = Webmachine::Application.new |
12 | | - application.dispatcher.add_route ["test"], Test::Resource |
| 17 | + sleep(0.1) # 'Wait' for temp_server to *really* close, not just TIME_WAIT |
| 18 | + port |
| 19 | + end |
13 | 20 |
|
14 | | - application.configure do |c| |
15 | | - c.ip = address |
16 | | - c.port = port |
| 21 | + def create_test_application(port) |
| 22 | + Webmachine::Application.new.tap do |application| |
| 23 | + application.dispatcher.add_route ["test"], Test::Resource |
| 24 | + |
| 25 | + application.configure do |c| |
| 26 | + c.ip = ADDRESS |
| 27 | + c.port = port |
| 28 | + end |
17 | 29 | end |
| 30 | + end |
18 | 31 |
|
19 | | - application |
| 32 | + def run_application(adapter_class, application) |
| 33 | + adapter = adapter_class.new(application) |
| 34 | + Thread.abort_on_exception = true |
| 35 | + Thread.new { adapter.run } |
20 | 36 | end |
21 | 37 |
|
22 | | - let(:client) do |
23 | | - client = Net::HTTP.new(application.configuration.ip, port) |
24 | | - # Wait until the server is responsive |
25 | | - timeout(5) do |
| 38 | + def wait_until_server_responds_to(client) |
| 39 | + Timeout.timeout(5, TestApplicationNotResponsive) do |
26 | 40 | begin |
27 | 41 | client.start |
28 | 42 | rescue Errno::ECONNREFUSED |
29 | 43 | sleep(0.01) |
30 | 44 | retry |
31 | 45 | end |
32 | 46 | end |
33 | | - client |
34 | 47 | end |
35 | 48 |
|
36 | | - before do |
37 | | - @adapter = described_class.new(application) |
| 49 | + before(:all) do |
| 50 | + @port = find_free_port |
| 51 | + application = create_test_application(@port) |
38 | 52 |
|
39 | | - Thread.abort_on_exception = true |
40 | | - @server_thread = Thread.new { @adapter.run } |
41 | | - sleep(0.01) |
| 53 | + adapter_class = described_class |
| 54 | + @server_thread = run_application(adapter_class, application) |
| 55 | + |
| 56 | + @client = Net::HTTP.new(application.configuration.ip, @port) |
| 57 | + wait_until_server_responds_to(client) |
42 | 58 | end |
43 | 59 |
|
44 | | - after do |
45 | | - client.finish |
| 60 | + after(:all) do |
| 61 | + @client.finish |
46 | 62 | @server_thread.kill |
47 | 63 | end |
48 | 64 |
|
49 | 65 | it "provides the request URI" do |
50 | 66 | request = Net::HTTP::Get.new("/test") |
51 | 67 | request["Accept"] = "test/response.request_uri" |
52 | 68 | response = client.request(request) |
53 | | - expect(response.body).to eq("http://#{address}:#{port}/test") |
| 69 | + expect(response.body).to eq("http://#{ADDRESS}:#{@port}/test") |
54 | 70 | end |
55 | 71 |
|
56 | 72 | # context do |
|
0 commit comments