diff options
Diffstat (limited to 'chef/spec/unit/rest_spec.rb')
-rw-r--r-- | chef/spec/unit/rest_spec.rb | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/chef/spec/unit/rest_spec.rb b/chef/spec/unit/rest_spec.rb new file mode 100644 index 0000000000..56c2954a1a --- /dev/null +++ b/chef/spec/unit/rest_spec.rb @@ -0,0 +1,228 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# 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 File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) +require 'uri' +require 'net/https' + +describe Chef::REST, "initialize method" do + it "should create a new Chef::REST" do + Chef::REST.new("url").should be_kind_of(Chef::REST) + end +end + +describe Chef::REST, "get_rest method" do + it "should create a url from the path and base url" do + URI.should_receive(:parse).with("url/monkey") + r = Chef::REST.new("url") + r.stub!(:run_request) + r.get_rest("monkey") + end + + it "should call run_request :GET with the composed url object" do + URI.stub!(:parse).and_return(true) + r = Chef::REST.new("url") + r.should_receive(:run_request).with(:GET, true, false, 10, false).and_return(true) + r.get_rest("monkey") + end +end + +describe Chef::REST, "delete_rest method" do + it "should create a url from the path and base url" do + URI.should_receive(:parse).with("url/monkey") + r = Chef::REST.new("url") + r.stub!(:run_request) + r.delete_rest("monkey") + end + + it "should call run_request :DELETE with the composed url object" do + URI.stub!(:parse).and_return(true) + r = Chef::REST.new("url") + r.should_receive(:run_request).with(:DELETE, true).and_return(true) + r.delete_rest("monkey") + end +end + +describe Chef::REST, "post_rest method" do + it "should create a url from the path and base url" do + URI.should_receive(:parse).with("url/monkey") + r = Chef::REST.new("url") + r.stub!(:run_request) + r.post_rest("monkey", "data") + end + + it "should call run_request :POST with the composed url object and data" do + URI.stub!(:parse).and_return(true) + r = Chef::REST.new("url") + r.should_receive(:run_request).with(:POST, true, "data").and_return(true) + r.post_rest("monkey", "data") + end +end + +describe Chef::REST, "put_rest method" do + it "should create a url from the path and base url" do + URI.should_receive(:parse).with("url/monkey") + r = Chef::REST.new("url") + r.stub!(:run_request) + r.put_rest("monkey", "data") + end + + it "should call run_request :PUT with the composed url object and data" do + URI.stub!(:parse).and_return(true) + r = Chef::REST.new("url") + r.should_receive(:run_request).with(:PUT, true, "data").and_return(true) + r.put_rest("monkey", "data") + end +end + +describe Chef::REST, "run_request method" do + before(:each) do + @r = Chef::REST.new("url") + @url_mock = mock("URI", :null_object => true) + @url_mock.stub!(:host).and_return("one") + @url_mock.stub!(:port).and_return("80") + @url_mock.stub!(:path).and_return("/") + @url_mock.stub!(:query).and_return("foo=bar") + @url_mock.stub!(:scheme).and_return("https") + @url_mock.stub!(:to_s).and_return("https://one:80/?foo=bar") + @http_response_mock = mock("Net::HTTPSuccess", :null_object => true) + @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(true) + @http_response_mock.stub!(:body).and_return("ninja") + @http_mock = mock("Net::HTTP", :null_object => true) + @http_mock.stub!(:verify_mode=).and_return(true) + @http_mock.stub!(:read_timeout=).and_return(true) + @http_mock.stub!(:use_ssl=).with(true).and_return(true) + @data_mock = mock("Data", :null_object => true) + @data_mock.stub!(:to_json).and_return('{ "one": "two" }') + @request_mock = mock("Request", :null_object => true) + @request_mock.stub!(:body=).and_return(true) + @request_mock.stub!(:method).and_return(true) + @request_mock.stub!(:path).and_return(true) + @http_mock.stub!(:request).and_return(@http_response_mock) + @tf_mock = mock(Tempfile, { :print => true, :close => true }) + Tempfile.stub!(:new).with("chef-rest").and_return(@tf_mock) + end + + def do_run_request(method=:GET, data=false, limit=10, raw=false) + Net::HTTP.stub!(:new).and_return(@http_mock) + @r.run_request(method, @url_mock, data, limit, raw) + end + + it "should raise an exception if the redirect limit is 0" do + lambda { @r.run_request(:GET, "/", false, 0)}.should raise_error(ArgumentError) + end + + it "should use SSL if the url starts with https" do + @url_mock.should_receive(:scheme).and_return("https") + @http_mock.should_receive(:use_ssl=).with(true).and_return(true) + do_run_request + end + + it "should set the OpenSSL Verify Mode to verify_none if requested" do + @http_mock.should_receive(:verify_mode=).and_return(true) + do_run_request + end + + it "should set a read timeout based on the rest_timeout config option" do + Chef::Config[:rest_timeout] = 10 + @http_mock.should_receive(:read_timeout=).with(10).and_return(true) + do_run_request + end + + it "should build a new HTTP GET request" do + Net::HTTP::Get.should_receive(:new).with("/?foo=bar", + { 'Accept' => 'application/json' } + ).and_return(@request_mock) + do_run_request + end + + it "should build a new HTTP POST request" do + Net::HTTP::Post.should_receive(:new).with("/", + { 'Accept' => 'application/json', "Content-Type" => 'application/json' } + ).and_return(@request_mock) + do_run_request(:POST, @data_mock) + end + + it "should build a new HTTP PUT request" do + Net::HTTP::Put.should_receive(:new).with("/", + { 'Accept' => 'application/json', "Content-Type" => 'application/json' } + ).and_return(@request_mock) + do_run_request(:PUT, @data_mock) + end + + it "should build a new HTTP DELETE request" do + Net::HTTP::Delete.should_receive(:new).with("/?foo=bar", + { 'Accept' => 'application/json' } + ).and_return(@request_mock) + do_run_request(:DELETE) + end + + it "should raise an error if the method is not GET/PUT/POST/DELETE" do + lambda { do_run_request(:MONKEY) }.should raise_error(ArgumentError) + end + + it "should run an http request" do + @http_mock.should_receive(:request).and_return(@http_response_mock) + do_run_request + end + + it "should return the body of the response on success" do + do_run_request.should eql("ninja") + end + + it "should inflate the body as to an object if JSON is returned" do + @http_response_mock.stub!(:[]).with('content-type').and_return("application/json") + JSON.should_receive(:parse).with("ninja").and_return(true) + do_run_request + end + + it "should call run_request again on a Redirect response" do + @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false) + @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(true) + @http_response_mock.stub!(:[]).with('location').and_return(@url_mock.path) + lambda { do_run_request(method=:GET, data=false, limit=1) }.should raise_error(ArgumentError) + end + + it "should raise an exception on an unsuccessful request" do + @http_response_mock.stub!(:kind_of?).with(Net::HTTPSuccess).and_return(false) + @http_response_mock.stub!(:kind_of?).with(Net::HTTPFound).and_return(false) + @http_response_mock.should_receive(:error!) + do_run_request + end + + it "should build a new HTTP GET request without the application/json accept header for raw reqs" do + Net::HTTP::Get.should_receive(:new).with("/?foo=bar", {}).and_return(@request_mock) + do_run_request(:GET, false, 10, true) + end + + it "should create a tempfile for the output of a raw request" do + Tempfile.should_receive(:new).with("chef-rest").and_return(@tf_mock) + do_run_request(:GET, false, 10, true).should eql(@tf_mock) + end + + it "should populate the tempfile with the value of the raw request" do + @tf_mock.should_receive(:print, "ninja").once.and_return(true) + do_run_request(:GET, false, 10, true) + end + + it "should close the tempfile if we're doing a raw request" do + @tf_mock.should_receive(:close).once.and_return(true) + do_run_request(:GET, false, 10, true) + end + +end |