summaryrefslogtreecommitdiff
path: root/spec/unit/provider
diff options
context:
space:
mode:
authorLamont Granquist <lamont@opscode.com>2013-04-01 16:52:57 -0700
committerLamont Granquist <lamont@opscode.com>2013-04-01 16:52:57 -0700
commit1f460cae553c16254f77b21bab83e8020dc89ca3 (patch)
tree307c02bbf5b2a037775dd73a3590974ed383bd49 /spec/unit/provider
parent4c1924d9adbbd334fb1d45f79aace3df68774b3e (diff)
downloadchef-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.rb248
-rw-r--r--spec/unit/provider/remote_file_spec.rb132
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)