From aab0ccb5d41913e050707bd6b40e5b820649c566 Mon Sep 17 00:00:00 2001 From: danielsdeleo Date: Tue, 31 Mar 2015 12:19:05 -0700 Subject: Extract socketless client and add specs --- spec/unit/http/socketless_chef_zero_client_spec.rb | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 spec/unit/http/socketless_chef_zero_client_spec.rb (limited to 'spec') diff --git a/spec/unit/http/socketless_chef_zero_client_spec.rb b/spec/unit/http/socketless_chef_zero_client_spec.rb new file mode 100644 index 0000000000..963cc9e8c4 --- /dev/null +++ b/spec/unit/http/socketless_chef_zero_client_spec.rb @@ -0,0 +1,174 @@ +#-- +# Author:: Daniel DeLeo () +# Copyright:: Copyright (c) 2015 Chef Software, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/http/socketless_chef_zero_client' + +describe Chef::HTTP::SocketlessChefZeroClient do + + let(:relative_url) { "" } + let(:uri_str) { "chefzero://localhost:1/#{relative_url}" } + let(:uri) { URI(uri_str) } + + subject(:zero_client) { Chef::HTTP::SocketlessChefZeroClient.new(uri) } + + it "has a host" do + expect(zero_client.host).to eq("localhost") + end + + it "has a port" do + expect(zero_client.port).to eq(1) + end + + describe "converting requests to rack format" do + + let(:expected_rack_req) do + { + "SCRIPT_NAME" => "", + "SERVER_NAME" => "localhost", + "REQUEST_METHOD" => method.to_s.upcase, + "PATH_INFO" => uri.path, + "QUERY_STRING" => uri.query, + "SERVER_PORT" => uri.port, + "HTTP_HOST" => "localhost:#{uri.port}", + "rack.url_scheme" => "chefzero", + } + end + + context "when the request has no body" do + + let(:method) { :GET } + let(:relative_url) { "clients" } + let(:headers) { { "Accept" => "application/json" } } + let(:body) { false } + let(:expected_body_str) { "" } + + let(:rack_req) { zero_client.req_to_rack(method, uri, body, headers) } + + it "creates a rack request env" do + # StringIO doesn't implement == in a way that we can compare, so we + # check rack.input individually and then iterate over everything else + expect(rack_req["rack.input"].string).to eq(expected_body_str) + expected_rack_req.each do |key, value| + expect(rack_req[key]).to eq(value) + end + end + + end + + context "when the request has a body" do + + let(:method) { :PUT } + let(:relative_url) { "clients/foo" } + let(:headers) { { "Accept" => "application/json" } } + let(:body) { "bunch o' JSON" } + let(:expected_body_str) { "bunch o' JSON" } + + let(:rack_req) { zero_client.req_to_rack(method, uri, body, headers) } + + it "creates a rack request env" do + # StringIO doesn't implement == in a way that we can compare, so we + # check rack.input individually and then iterate over everything else + expect(rack_req["rack.input"].string).to eq(expected_body_str) + expected_rack_req.each do |key, value| + expect(rack_req[key]).to eq(value) + end + end + + end + + end + + describe "converting responses to Net::HTTP objects" do + + let(:net_http_response) { zero_client.to_net_http(code, headers, body) } + + context "when the request was successful (2XX)" do + + let(:code) { 200 } + let(:headers) { { "Content-Type" => "Application/JSON" } } + let(:body) { [ "bunch o' JSON" ] } + + it "creates a Net::HTTP success response object" do + expect(net_http_response).to be_a_kind_of(Net::HTTPOK) + expect(net_http_response.read_body).to eq("bunch o' JSON") + expect(net_http_response["content-type"]).to eq("Application/JSON") + end + + it "does not fail when calling read_body with a block" do + expect(net_http_response.read_body {|chunk| chunk }).to eq("bunch o' JSON") + end + + end + + context "when the requested object doesn't exist (404)" do + + let(:code) { 404 } + let(:headers) { { "Content-Type" => "Application/JSON" } } + let(:body) { [ "nope" ] } + + it "creates a Net::HTTPNotFound response object" do + expect(net_http_response).to be_a_kind_of(Net::HTTPNotFound) + end + end + + end + + describe "request-response round trip" do + + let(:method) { :GET } + let(:relative_url) { "clients" } + let(:headers) { { "Accept" => "application/json" } } + let(:body) { false } + + let(:expected_rack_req) do + { + "SCRIPT_NAME" => "", + "SERVER_NAME" => "localhost", + "REQUEST_METHOD" => method.to_s.upcase, + "PATH_INFO" => uri.path, + "QUERY_STRING" => uri.query, + "SERVER_PORT" => uri.port, + "HTTP_HOST" => "localhost:#{uri.port}", + "rack.url_scheme" => "chefzero", + "rack.input" => an_instance_of(StringIO), + } + end + + + let(:response_code) { 200 } + let(:response_headers) { { "Content-Type" => "Application/JSON" } } + let(:response_body) { [ "bunch o' JSON" ] } + + let(:rack_response) { [ response_code, response_headers, response_body ] } + + let(:response) { zero_client.request(method, uri, body, headers) } + + before do + expect(ChefZero::SocketlessServerMap).to receive(:request).with(1, expected_rack_req).and_return(rack_response) + end + + it "makes a rack request to Chef Zero and returns the response as a Net::HTTP object" do + _client, net_http_response = response + expect(net_http_response).to be_a_kind_of(Net::HTTPOK) + expect(net_http_response.code).to eq("200") + expect(net_http_response.body).to eq("bunch o' JSON") + end + + end + +end -- cgit v1.2.1