diff options
author | Lamont Granquist <lamont@opscode.com> | 2013-04-01 16:52:57 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@opscode.com> | 2013-04-01 16:52:57 -0700 |
commit | 1f460cae553c16254f77b21bab83e8020dc89ca3 (patch) | |
tree | 307c02bbf5b2a037775dd73a3590974ed383bd49 /spec/unit/provider | |
parent | 4c1924d9adbbd334fb1d45f79aace3df68774b3e (diff) | |
download | chef-1f460cae553c16254f77b21bab83e8020dc89ca3.tar.gz |
refactoring into remote_file content spec
Diffstat (limited to 'spec/unit/provider')
-rw-r--r-- | spec/unit/provider/remote_file/content_spec.rb | 248 | ||||
-rw-r--r-- | spec/unit/provider/remote_file_spec.rb | 132 |
2 files changed, 288 insertions, 92 deletions
diff --git a/spec/unit/provider/remote_file/content_spec.rb b/spec/unit/provider/remote_file/content_spec.rb new file mode 100644 index 0000000000..ac8252510b --- /dev/null +++ b/spec/unit/provider/remote_file/content_spec.rb @@ -0,0 +1,248 @@ +# +# Author:: Lamont Granquist (<lamont@opscode.com>) +# Copyright:: Copyright (c) 2013 Opscode, 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 'spec_helper' + +describe Chef::Provider::RemoteFile::Content do + + # + # mock setup + # + + let(:current_resource) do + mock("Chef::Provider::RemoteFile::Resource (current)", :source => nil) + end + + let(:source) { [ "http://opscode.com/seattle.txt" ] } + + let(:new_resource) do + mock("Chef::Provider::RemoteFile::Resource (new)", :source => source, :etag => nil, :last_modified => nil) + end + + let(:run_context) { mock("Chef::RunContext") } + + # + # subject + # + let(:content) do + Chef::Provider::RemoteFile::Content.new(new_resource, current_resource, run_context) + end + + describe "when the checksum of the current_resource matches the checksum set on the resource" do + before do + new_resource.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") + current_resource.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") + end + + it "should return nil for the tempfile" do + content.tempfile.should be_nil + end + end + + describe "when the checksum of the current_resource does not match the checksum set on the resource" do + before do + # FIXME: test one or the other nil, test both not nil and not equal, abuse the regexp a little + new_resource.stub!(:checksum).and_return(nil) + current_resource.stub!(:checksum).and_return(nil) + @uri = mock("URI") + @sanitized_uri = mock("URI") + URI.should_receive(:parse).with(new_resource.source[0]).and_return(@uri) + Chef::Provider::RemoteFile::Util.should_receive(:uri_for_cache).with(@uri).and_return(@sanitized_uri) + end + + describe "when the fetcher returns nil for the tempfile" do + before do + @result = mock("Chef::Provider::RemoteFile::Result", :raw_file => nil, :etag => nil, :mtime => nil) + http_fetcher = mock("Chef::Provider::RemoteFile::HTTP", :fetch => @result) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri, new_resource, current_resource).and_return(http_fetcher) + end + + it "should return nil for the tempfile" do + content.tempfile.should be_nil + end + + it "should return the raw_file_source when the accessor is called after getting the tempfile" do + content.tempfile + content.raw_file_source.should == @sanitized_uri + end + + it "should not set the etags on the new resource" do + new_resource.should_not_receive(:etag).with(@result.etag) + content.tempfile + end + + it "should not set the mtime on the new resource" do + new_resource.should_not_receive(:mtime).with(@result.mtime) + content.tempfile + end + end + + describe "when the fetcher returns a result with a valid tempfile" do + before do + @tempfile = mock("Tempfile") + mtime = Time.now + @result = mock("Chef::Provider::RemoteFile::Result", :raw_file => @tempfile, :etag => "etag", :mtime => mtime) + http_fetcher = mock("Chef::Provider::RemoteFile::HTTP", :fetch => @result) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri, new_resource, current_resource).and_return(http_fetcher) + end + + it "should return the tempfile object to the caller" do + content.tempfile.should == @tempfile + end + + it "should return the raw_file_source when the accessor is called after getting the tempfile" do + content.tempfile + content.raw_file_source.should == @sanitized_uri + end + + it "should set the etags on the new resource" do + new_resource.should_receive(:etag).with(@result.etag) + content.tempfile + end + + it "should set the mtime on the new resource" do + new_resource.should_receive(:last_modified).with(@result.mtime) + content.tempfile + end + end + end + + describe "when the fetcher throws an exception" do + before do + new_resource.stub!(:checksum).and_return(nil) + current_resource.stub!(:checksum).and_return(nil) + @uri = mock("URI") + URI.should_receive(:parse).with(new_resource.source[0]).and_return(@uri) + http_fetcher = mock("Chef::Provider::RemoteFile::HTTP") + http_fetcher.should_receive(:fetch).and_raise(Errno::ECONNREFUSED) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri, new_resource, current_resource).and_return(http_fetcher) + Chef::Provider::RemoteFile::Util.should_not_receive(:uri_for_cache) + end + + it "should propagate the error back to the caller" do + lambda { content.tempfile }.should raise_error(Errno::ECONNREFUSED) + end + end + + describe "when there is an array of sources and the first fails" do + + let(:source) { [ "http://opscode.com/seattle.txt", "http://opscode.com/nyc.txt" ] } + before do + new_resource.stub!(:checksum).and_return(nil) + current_resource.stub!(:checksum).and_return(nil) + @uri0 = mock("URI0") + @uri1 = mock("URI1") + URI.should_receive(:parse).with(new_resource.source[0]).and_return(@uri0) + URI.should_receive(:parse).with(new_resource.source[1]).and_return(@uri1) + @http_fetcher_throws_exception = mock("Chef::Provider::RemoteFile::HTTP") + @http_fetcher_throws_exception.should_receive(:fetch).at_least(:once).and_raise(Errno::ECONNREFUSED) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri0, new_resource, current_resource).and_return(@http_fetcher_throws_exception) + end + + describe "when the second url succeeds" do + before do + @tempfile = mock("Tempfile") + mtime = Time.now + @result = mock("Chef::Provider::RemoteFile::Result", :raw_file => @tempfile, :etag => "etag", :mtime => mtime) + http_fetcher_works = mock("Chef::Provider::RemoteFile::HTTP", :fetch => @result) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri1, new_resource, current_resource).and_return(http_fetcher_works) + @sanitized_uri = mock("URI") + Chef::Provider::RemoteFile::Util.should_receive(:uri_for_cache).with(@uri1).and_return(@sanitized_uri) + end + + it "should return a valid tempfile" do + content.tempfile.should == @tempfile + end + + it "should return the raw_file_source when the accessor is called after getting the tempfile" do + content.tempfile + content.raw_file_source.should == @sanitized_uri + end + + it "should set the etags on the new resource" do + new_resource.should_receive(:etag).with(@result.etag) + content.tempfile + end + + it "should set the mtime on the new resource" do + new_resource.should_receive(:last_modified).with(@result.mtime) + content.tempfile + end + + it "should not mutate the new_resource" do + content.tempfile + new_resource.source.length.should == 2 + end + end + + describe "when both urls fail" do + before do + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri1, new_resource, current_resource).and_return(@http_fetcher_throws_exception) + Chef::Provider::RemoteFile::Util.should_not_receive(:uri_for_cache) + end + + it "should propagate the error back to the caller" do + lambda { content.tempfile }.should raise_error(Errno::ECONNREFUSED) + end + end + end + + describe "when there is an array of sources and the first succeeds" do + let(:source) { [ "http://opscode.com/seattle.txt", "http://opscode.com/nyc.txt" ] } + before do + new_resource.stub!(:checksum).and_return(nil) + current_resource.stub!(:checksum).and_return(nil) + @uri0 = mock("URI0") + URI.should_receive(:parse).with(new_resource.source[0]).and_return(@uri0) + URI.should_not_receive(:parse).with(new_resource.source[1]) + @tempfile = mock("Tempfile") + mtime = Time.now + @result = mock("Chef::Provider::RemoteFile::Result", :raw_file => @tempfile, :etag => "etag", :mtime => mtime) + http_fetcher_works = mock("Chef::Provider::RemoteFile::HTTP", :fetch => @result) + Chef::Provider::RemoteFile::Fetcher.should_receive(:for_resource).with(@uri0, new_resource, current_resource).and_return(http_fetcher_works) + @sanitized_uri = mock("URI") + Chef::Provider::RemoteFile::Util.should_receive(:uri_for_cache).with(@uri0).and_return(@sanitized_uri) + end + + it "should return a valid tempfile" do + content.tempfile.should == @tempfile + end + + it "should return the raw_file_source when the accessor is called after getting the tempfile" do + content.tempfile + content.raw_file_source.should == @sanitized_uri + end + + it "should set the etags on the new resource" do + new_resource.should_receive(:etag).with(@result.etag) + content.tempfile + end + + it "should set the mtime on the new resource" do + new_resource.should_receive(:last_modified).with(@result.mtime) + content.tempfile + end + + it "should not mutate the new_resource" do + content.tempfile + new_resource.source.length.should == 2 + end + end + +end + diff --git a/spec/unit/provider/remote_file_spec.rb b/spec/unit/provider/remote_file_spec.rb index 7b7cd23b46..f77125cabd 100644 --- a/spec/unit/provider/remote_file_spec.rb +++ b/spec/unit/provider/remote_file_spec.rb @@ -38,6 +38,20 @@ describe Chef::Provider::RemoteFile do content = mock('Chef::Provider::File::Content::RemoteFile') end + let(:node) { double('Chef::Node') } + let(:events) { double('Chef::Events').as_null_object } # mock all the methods + let(:run_context) { double('Chef::RunContext', :node => node, :events => events) } + let(:enclosing_directory) { File.expand_path(File.join(CHEF_SPEC_DATA, "templates")) } + let(:resource_path) { File.expand_path(File.join(enclosing_directory, "seattle.txt")) } + + # Subject + + let(:provider) do + provider = described_class.new(resource, run_context) + provider.stub!(:content).and_return(content) + provider + end + it_behaves_like Chef::Provider::File #describe Chef::Provider::RemoteFile, "action_create" do @@ -56,85 +70,38 @@ describe Chef::Provider::RemoteFile do # @provider.stub!(:load_current_resource) # end - describe "when checking if the file is at the target version" do - it "considers the current file to be at the target version if it exists and matches the user-provided checksum" do - @provider.current_resource = @resource.dup - @resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") - @provider.current_resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") - @provider.current_resource_matches_target_checksum?.should be_true - end - end + # FIXME: move to content +# describe "when checking if the file is at the target version" do +# it "considers the current file to be at the target version if it exists and matches the user-provided checksum" do +# provider.current_resource = resource.dup +# resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") +# provider.current_resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") +# provider.current_resource_matches_target_checksum?.should be_true +# end +# end describe "when fetching the file from the remote" do before(:each) do - @tempfile = Tempfile.new("chef-rspec-remote_file_spec-line#{__LINE__}--") - - @rest = mock(Chef::REST, { }) - Chef::REST.stub!(:new).and_return(@rest) - @rest.stub!(:streaming_request).and_return(@tempfile) - @rest.stub!(:last_response).and_return({}) - @resource.cookbook_name = "monkey" - - @provider.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") - @provider.current_resource = @resource.clone - @provider.current_resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") - File.stub!(:exists?).and_return(true) - FileUtils.stub!(:cp).and_return(true) - Chef::Platform.stub!(:find_platform_and_version).and_return([ :mac_os_x, "10.5.1" ]) + #@tempfile = Tempfile.new("chef-rspec-remote_file_spec-line#{__LINE__}--") + + #@rest = mock(Chef::REST, { }) + #Chef::REST.stub!(:new).and_return(@rest) + #@rest.stub!(:streaming_request).and_return(@tempfile) + #@rest.stub!(:last_response).and_return({}) + resource.cookbook_name = "monkey" + resource.source("http://opscode.com/seattle.txt") + + provider.stub!(:checksum).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") + provider.current_resource = resource.clone + provider.current_resource.checksum("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") + #File.stub!(:exists?).and_return(true) + #FileUtils.stub!(:cp).and_return(true) + #Chef::Platform.stub!(:find_platform_and_version).and_return([ :mac_os_x, "10.5.1" ]) + setup_normal_file end after do - @tempfile.close! - end - - before do - @resource.source("http://opscode.com/seattle.txt") - end - - describe "and the target location's enclosing directory does not exist" do - before do - @resource.path("/tmp/this/path/does/not/exist/file.txt") - end - - it "raises a specific error describing the problem" do - lambda {@provider.run_action(:create)}.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist) - end - end - - shared_examples_for "source specified with multiple URIs" do - it "should try to download the next URI when the first one fails" do - @rest.should_receive(:streaming_request).with(URI.parse("http://foo"), {}).once.and_raise(SocketError) - @rest.should_receive(:streaming_request).with(URI.parse("http://bar"), {}).once.and_return(@tempfile) - @provider.run_action(:create) - end - - it "should raise an exception when all the URIs fail" do - @rest.should_receive(:streaming_request).with(URI.parse("http://foo"), {}).once.and_raise(SocketError) - @rest.should_receive(:streaming_request).with(URI.parse("http://bar"), {}).once.and_raise(SocketError) - lambda { @provider.run_action(:create) }.should raise_error(SocketError) - end - - it "should download from only one URI when the first one works" do - @rest.should_receive(:streaming_request).once.and_return(@tempfile) - @provider.run_action(:create) - end - - end - - describe "and the source specifies multiple URIs using multiple arguments" do - it_should_behave_like "source specified with multiple URIs" - - before(:each) do - @resource.source("http://foo", "http://bar") - end - end - - describe "and the source specifies multiple URIs using an array" do - it_should_behave_like "source specified with multiple URIs" - - before(:each) do - @resource.source([ "http://foo", "http://bar" ]) - end + #@tempfile.close! end describe "and the resource specifies a checksum" do @@ -262,11 +229,6 @@ describe Chef::Provider::RemoteFile do lambda { @provider.run_action(:create) }.should raise_error(Net::HTTPServerException) end - it "should checksum the raw file" do - @provider.should_receive(:checksum).with(@tempfile.path).and_return("0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa") - @provider.run_action(:create) - end - describe "when the target file does not exist" do before do ::File.stub!(:exists?).with(@resource.path).and_return(false) @@ -284,13 +246,6 @@ describe Chef::Provider::RemoteFile do @provider.run_action(:create) @resource.should be_updated end - - describe "and create_if_missing is invoked" do - it "should invoke action_create" do - @provider.should_receive(:action_create) - @provider.run_action(:create_if_missing) - end - end end describe "when the target file already exists" do @@ -306,13 +261,6 @@ describe Chef::Provider::RemoteFile do @provider.stub!(:get_from_server).and_return(@tempfile) end - describe "and create_if_missing is invoked" do - it "should take no action" do - @provider.should_not_receive(:action_create) - @provider.run_action(:create_if_missing) - end - end - describe "and the file downloaded from the remote is identical to the current" do it "shouldn't backup the original file" do @provider.should_not_receive(:backup).with(@resource.path) |