require "webmachine/spec/test_resource" require "net/http" ADDRESS = "127.0.0.1" shared_examples_for :adapter_lint do attr_reader :client class TestApplicationNotResponsive < Timeout::Error; end def find_free_port temp_server = TCPServer.new(ADDRESS, 0) port = temp_server.addr[1] temp_server.close # only frees Ruby resource, socket is in TIME_WAIT at OS level # so we can't have our adapter use it too quickly sleep(0.1) # 'Wait' for temp_server to *really* close, not just TIME_WAIT port end def create_test_application(port) Webmachine::Application.new.tap do |application| application.dispatcher.add_route ["test"], Test::Resource application.configure do |c| c.ip = ADDRESS c.port = port end end end def run_application(adapter_class, application) adapter = adapter_class.new(application) Thread.abort_on_exception = true Thread.new { adapter.run } end def wait_until_server_responds_to(client) Timeout.timeout(5, TestApplicationNotResponsive) do begin client.start rescue Errno::ECONNREFUSED sleep(0.01) retry end end end before(:all) do @port = find_free_port application = create_test_application(@port) adapter_class = described_class @server_thread = run_application(adapter_class, application) @client = Net::HTTP.new(application.configuration.ip, @port) wait_until_server_responds_to(client) end after(:all) do @client.finish @server_thread.kill end it "provides the request URI" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.request_uri" response = client.request(request) expect(response.body).to eq("http://#{ADDRESS}:#{@port}/test") end # context do # let(:address) { "::1" } # it "provides the IPv6 request URI" do # request = Net::HTTP::Get.new("/test") # request["Accept"] = "test/response.request_uri" # response = client.request(request) # expect(response.body).to eq("http://[#{address}]:#{port}/test") # end # end it "provides a string-like request body" do request = Net::HTTP::Put.new("/test") request.body = "Hello, World!" request["Content-Type"] = "test/request.stringbody" response = client.request(request) expect(response["Content-Length"]).to eq("21") expect(response.body).to eq("String: Hello, World!") end it "provides an enumerable request body" do request = Net::HTTP::Put.new("/test") request.body = "Hello, World!" request["Content-Type"] = "test/request.enumbody" response = client.request(request) expect(response["Content-Length"]).to eq("19") expect(response.body).to eq("Enum: Hello, World!") end it "handles missing pages" do request = Net::HTTP::Get.new("/missing") response = client.request(request) expect(response.code).to eq("404") expect(response["Content-Type"]).to eq("text/html") end it "handles empty response bodies" do request = Net::HTTP::Post.new("/test") request.body = "" response = client.request(request) expect(response.code).to eq("204") expect(["0", nil]).to include(response["Content-Length"]) expect(response.body).to be_nil end it "handles string response bodies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.stringbody" response = client.request(request) expect(response["Content-Length"]).to eq("20") expect(response.body).to eq("String response body") end it "handles enumerable response bodies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.enumbody" response = client.request(request) expect(response["Transfer-Encoding"]).to eq("chunked") expect(response.body).to eq("Enumerable response body") end it "handles proc response bodies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.procbody" response = client.request(request) expect(response["Transfer-Encoding"]).to eq("chunked") expect(response.body).to eq("Proc response body") end it "handles fiber response bodies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.fiberbody" response = client.request(request) expect(response["Transfer-Encoding"]).to eq("chunked") expect(response.body).to eq("Fiber response body") end it "handles io response bodies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.iobody" response = client.request(request) expect(response["Content-Length"]).to eq("17") expect(response.body).to eq("IO response body\n") end it "handles request cookies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.cookies" request["Cookie"] = "echo=echocookie" response = client.request(request) expect(response.body).to eq("echocookie") end it "handles response cookies" do request = Net::HTTP::Get.new("/test") request["Accept"] = "test/response.cookies" response = client.request(request) expect(response["Set-Cookie"]).to eq("cookie=monster, rodeo=clown") end end