diff options
author | sawanoboly <sawanoboriyu@higanworks.com> | 2014-08-04 15:03:02 +0900 |
---|---|---|
committer | sawanoboly <sawanoboriyu@higanworks.com> | 2014-08-04 15:03:02 +0900 |
commit | e717a8a050f1e7d0b8419b1a058b98f4f9ef294f (patch) | |
tree | 35169e6630451a0f74f2dc89d3a68df6bf5ed9b6 /spec | |
parent | e2d090be774b1c2e18c4864884588e29ec2bc3bb (diff) | |
parent | 930d12091511aa2d547366796ea49f4e26f18253 (diff) | |
download | chef-e717a8a050f1e7d0b8419b1a058b98f4f9ef294f.tar.gz |
Merge remote-tracking branch 'upstream/master' into use_shared_path_for_deploy_resource
Diffstat (limited to 'spec')
34 files changed, 969 insertions, 324 deletions
diff --git a/spec/functional/resource/base.rb b/spec/functional/resource/base.rb index 056db39877..cdb52fbc1b 100644 --- a/spec/functional/resource/base.rb +++ b/spec/functional/resource/base.rb @@ -16,16 +16,6 @@ # limitations under the License. # -require 'spec_helper' - -def ohai - # provider is platform-dependent, we need platform ohai data: - @OHAI_SYSTEM ||= begin - ohai = Ohai::System.new - ohai.all_plugins("platform") - ohai - end -end def run_context @run_context ||= begin diff --git a/spec/functional/resource/cookbook_file_spec.rb b/spec/functional/resource/cookbook_file_spec.rb index 173dac8268..7797ed0041 100644 --- a/spec/functional/resource/cookbook_file_spec.rb +++ b/spec/functional/resource/cookbook_file_spec.rb @@ -40,7 +40,7 @@ describe Chef::Resource::CookbookFile do # set up cookbook collection for this run to use, based on our # spec data. cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, 'cookbooks')) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo) loader = Chef::CookbookLoader.new(cookbook_repo) loader.load_cookbooks cookbook_collection = Chef::CookbookCollection.new(loader) diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/package_spec.rb index 797f308cf9..548db40e79 100644 --- a/spec/functional/resource/package_spec.rb +++ b/spec/functional/resource/package_spec.rb @@ -135,9 +135,7 @@ describe Chef::Resource::Package, metadata do cookbook_path = File.join(CHEF_SPEC_DATA, "cookbooks") cl = Chef::CookbookLoader.new(cookbook_path) cl.load_cookbooks - Chef::Cookbook::FileVendor.on_create do |manifest| - Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_path) - end + Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_path) Chef::CookbookCollection.new(cl) end diff --git a/spec/functional/resource/remote_directory_spec.rb b/spec/functional/resource/remote_directory_spec.rb index 70e575abb0..f9eb20711e 100644 --- a/spec/functional/resource/remote_directory_spec.rb +++ b/spec/functional/resource/remote_directory_spec.rb @@ -26,7 +26,7 @@ describe Chef::Resource::RemoteDirectory do def create_resource cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo) node = Chef::Node.new cl = Chef::CookbookLoader.new(cookbook_repo) cl.load_cookbooks diff --git a/spec/functional/resource/template_spec.rb b/spec/functional/resource/template_spec.rb index 7816d6357b..fefd995743 100644 --- a/spec/functional/resource/template_spec.rb +++ b/spec/functional/resource/template_spec.rb @@ -37,7 +37,7 @@ describe Chef::Resource::Template do def create_resource cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo) cl = Chef::CookbookLoader.new(cookbook_repo) cl.load_cookbooks cookbook_collection = Chef::CookbookCollection.new(cl) diff --git a/spec/integration/knife/chef_fs_data_store_spec.rb b/spec/integration/knife/chef_fs_data_store_spec.rb index e8a3b3dde5..7e55aa7319 100644 --- a/spec/integration/knife/chef_fs_data_store_spec.rb +++ b/spec/integration/knife/chef_fs_data_store_spec.rb @@ -141,7 +141,7 @@ EOM end it 'knife cookbook upload works' do - knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} x").should_succeed <<EOM + knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} x").should_succeed :stderr => <<EOM Uploading x [1.0.0] Uploaded 1 cookbook. EOM @@ -199,7 +199,7 @@ EOM end it 'knife cookbook upload works' do - knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} z").should_succeed <<EOM + knife("cookbook upload -z --cookbook-path #{path_to('cookbooks_to_upload')} z").should_succeed :stderr => <<EOM Uploading z [1.0.0] Uploaded 1 cookbook. EOM diff --git a/spec/support/platform_helpers.rb b/spec/support/platform_helpers.rb index 75ab0c9cde..ad7104d170 100644 --- a/spec/support/platform_helpers.rb +++ b/spec/support/platform_helpers.rb @@ -27,6 +27,11 @@ def windows? !!(RUBY_PLATFORM =~ /mswin|mingw|windows/) end +def ohai + # This is defined in spec_helper; it has the `platform` populated. + OHAI_SYSTEM +end + require 'wmi-lite/wmi' if windows? def windows_domain_joined? diff --git a/spec/unit/cookbook/file_vendor_spec.rb b/spec/unit/cookbook/file_vendor_spec.rb new file mode 100644 index 0000000000..4fad7d5808 --- /dev/null +++ b/spec/unit/cookbook/file_vendor_spec.rb @@ -0,0 +1,78 @@ +#-- +# Author:: Daniel DeLeo (<dan@getchef.com>) +# Copyright:: Copyright (c) 2014 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 'spec_helper' + +describe Chef::Cookbook::FileVendor do + + let(:file_vendor_class) { Class.new(described_class) } + + # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest + let(:manifest) { {:cookbook_name => "bob"} } + + context "when configured to fetch files over http" do + + let(:http) { double("Chef::REST") } + + before do + file_vendor_class.fetch_from_remote(http) + end + + it "sets the vendor class to RemoteFileVendor" do + expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::RemoteFileVendor) + end + + it "sets the initialization options to the given http object" do + expect(file_vendor_class.initialization_options).to eq(http) + end + + it "creates a RemoteFileVendor for a given manifest" do + file_vendor = file_vendor_class.create_from_manifest(manifest) + expect(file_vendor).to be_a_kind_of(Chef::Cookbook::RemoteFileVendor) + expect(file_vendor.rest).to eq(http) + expect(file_vendor.cookbook_name).to eq("bob") + end + + end + + context "when configured to load files from disk" do + + let(:cookbook_path) { %w[/var/chef/cookbooks /var/chef/other_cookbooks] } + + before do + file_vendor_class.fetch_from_disk(cookbook_path) + end + + it "sets the vendor class to FileSystemFileVendor" do + expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::FileSystemFileVendor) + end + + it "sets the initialization options to the given cookbook paths" do + expect(file_vendor_class.initialization_options).to eq(cookbook_path) + end + + it "creates a FileSystemFileVendor for a given manifest" do + file_vendor = file_vendor_class.create_from_manifest(manifest) + expect(file_vendor).to be_a_kind_of(Chef::Cookbook::FileSystemFileVendor) + expect(file_vendor.cookbook_name).to eq("bob") + expect(file_vendor.repo_paths).to eq(cookbook_path) + end + + end + +end + diff --git a/spec/unit/cookbook/synchronizer_spec.rb b/spec/unit/cookbook/synchronizer_spec.rb index c52593287a..2b040f3c95 100644 --- a/spec/unit/cookbook/synchronizer_spec.rb +++ b/spec/unit/cookbook/synchronizer_spec.rb @@ -5,302 +5,517 @@ require 'chef/cookbook_version' describe Chef::CookbookCacheCleaner do describe "when cleaning up unused cookbook components" do - before do - @cleaner = Chef::CookbookCacheCleaner.instance - @cleaner.reset! + let(:cleaner) do + cleaner = Chef::CookbookCacheCleaner.instance + cleaner.reset! + cleaner end - it "removes all files that belong to unused cookbooks" do - end + let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") } - it "removes all files not validated during the chef run" do - file_cache = double("Chef::FileCache with files from unused cookbooks") - unused_template_files = %w{cookbooks/unused/templates/default/foo.conf.erb cookbooks/unused/tempaltes/default/bar.conf.erb} - valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb} - @cleaner.mark_file_as_valid('cookbooks/valid1/recipes/default.rb') - @cleaner.mark_file_as_valid('cookbooks/valid2/recipes/default.rb') - file_cache.should_receive(:find).with(File.join(%w{cookbooks ** *})).and_return(valid_cached_cb_files + unused_template_files) - file_cache.should_receive(:delete).with('cookbooks/unused/templates/default/foo.conf.erb') - file_cache.should_receive(:delete).with('cookbooks/unused/tempaltes/default/bar.conf.erb') - cookbook_hash = {"valid1"=> {}, "valid2" => {}} - @cleaner.stub(:cache).and_return(file_cache) - @cleaner.cleanup_file_cache + let(:unused_template_files) do + %w{ + cookbooks/unused/templates/default/foo.conf.erb + cookbooks/unused/tempaltes/default/bar.conf.erb + } end - describe "on chef-solo" do - before do - Chef::Config[:solo] = true - end + let(:valid_cached_cb_files) do + %w{ + cookbooks/valid1/recipes/default.rb + cookbooks/valid2/recipes/default.rb + } + end - after do - Chef::Config[:solo] = false + before do + valid_cached_cb_files.each do |cbf| + cleaner.mark_file_as_valid(cbf) end + end - it "does not remove anything" do - @cleaner.cache.stub(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}) - @cleaner.cache.should_not_receive(:delete) - @cleaner.cleanup_file_cache + it "removes all files not validated during the chef run" do + expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + unused_template_files) + unused_template_files.each do |cbf| + expect(file_cache).to receive(:delete).with(cbf) end + cookbook_hash = {"valid1"=> {}, "valid2" => {}} + allow(cleaner).to receive(:cache).and_return(file_cache) + cleaner.cleanup_file_cache + end + it "does not remove anything when skip_removal is true" do + cleaner.skip_removal = true + allow(cleaner.cache).to receive(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}) + expect(cleaner.cache).not_to receive(:delete) + cleaner.cleanup_file_cache end + it "does not remove anything on chef-solo" do + Chef::Config[:solo] = true + allow(cleaner.cache).to receive(:find).and_return(%w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb}) + expect(cleaner.cache).not_to receive(:delete) + cleaner.cleanup_file_cache + end end end describe Chef::CookbookSynchronizer do - before do + let(:cookbook_a_default_recipe) do + { + "path" => "recipes/default.rb", + "url" => "http://chef.example.com/abc123", + "checksum" => "abc123", + } + end + + let(:cookbook_a_default_attrs) do + { + "path" => "attributes/default.rb", + "url" => "http://chef.example.com/abc456", + "checksum" => "abc456", + } + end + + let(:cookbook_a_template) do + { + "path" => "templates/default/apache2.conf.erb", + "url" => "http://chef.example.com/ffffff", + "checksum" => "abc125", + } + end + + let(:cookbook_a_file) do + { + "path" => "files/default/megaman.conf", + "url" => "http://chef.example.com/megaman.conf", + "checksum" => "abc124", + } + end + + let(:cookbook_a_manifest) do segments = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ] - @cookbook_manifest = {} - @cookbook_a = Chef::CookbookVersion.new("cookbook_a") - @cookbook_a_manifest = segments.inject({}) {|h, segment| h[segment.to_s] = []; h} - @cookbook_a_default_recipe = { "path" => "recipes/default.rb", - "url" => "http://chef.example.com/abc123", - "checksum" => "abc123" } - @cookbook_a_manifest["recipes"] = [ @cookbook_a_default_recipe ] - - @cookbook_a_default_attrs = { "path" => "attributes/default.rb", - "url" => "http://chef.example.com/abc456", - "checksum" => "abc456" } - @cookbook_a_manifest["attributes"] = [ @cookbook_a_default_attrs ] - @cookbook_a_manifest["templates"] = [{"path" => "templates/default/apache2.conf.erb", "url" => "http://chef.example.com/ffffff"}] - @cookbook_a_manifest["files"] = [{"path" => "files/default/megaman.conf", "url" => "http://chef.example.com/megaman.conf"}] - @cookbook_a.manifest = @cookbook_a_manifest - @cookbook_manifest["cookbook_a"] = @cookbook_a - - @events = Chef::EventDispatch::Dispatcher.new - @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_manifest, @events) + cookbook_a_manifest = segments.inject({}) {|h, segment| h[segment.to_s] = []; h} + cookbook_a_manifest["recipes"] = [ cookbook_a_default_recipe ] + cookbook_a_manifest["attributes"] = [ cookbook_a_default_attrs ] + cookbook_a_manifest["templates"] = [ cookbook_a_template ] + cookbook_a_manifest["files"] = [ cookbook_a_file ] + cookbook_a_manifest + end + + let(:cookbook_a) do + cookbook_a = Chef::CookbookVersion.new("cookbook_a") + cookbook_a.manifest = cookbook_a_manifest + cookbook_a + end + + let(:cookbook_manifest) do + { + "cookbook_a" => cookbook_a + } + end + + let(:events) { Chef::EventDispatch::Dispatcher.new } + + let(:no_lazy_load) { true } + + let(:synchronizer) do + Chef::Config[:no_lazy_load] = no_lazy_load + Chef::CookbookSynchronizer.new(cookbook_manifest, events) end it "lists the cookbook names" do - @synchronizer.cookbook_names.should == %w[cookbook_a] + expect(synchronizer.cookbook_names).to eq(%w[cookbook_a]) end it "lists the cookbook manifests" do - @synchronizer.cookbooks.should == [@cookbook_a] + expect(synchronizer.cookbooks).to eq([cookbook_a]) end - context "when the cache contains unneeded cookbooks" do - before do - @file_cache = double("Chef::FileCache with files from unused cookbooks") - @valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb} - @obsolete_cb_files = %w{cookbooks/old1/recipes/default.rb cookbooks/old2/recipes/default.rb} + context "#clear_obsoleted_cookbooks" do + after do + # Singletons == Global State == Bad + Chef::CookbookCacheCleaner.instance.skip_removal = nil + end - @cookbook_hash = {"valid1"=> {}, "valid2" => {}} + it "behaves correctly when remove_obsoleted_files is false" do + synchronizer.remove_obsoleted_files = false + expect(synchronizer).not_to receive(:remove_old_cookbooks) + expect(synchronizer).to receive(:remove_deleted_files) + synchronizer.clear_obsoleted_cookbooks + expect(Chef::CookbookCacheCleaner.instance.skip_removal).to be true + end + + it "behaves correctly when remove_obsoleted_files is true" do + synchronizer.remove_obsoleted_files = true + expect(synchronizer).to receive(:remove_old_cookbooks) + expect(synchronizer).to receive(:remove_deleted_files) + synchronizer.clear_obsoleted_cookbooks + expect(Chef::CookbookCacheCleaner.instance.skip_removal).to be nil + end + end + + context "#remove_old_cookbooks" do + let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") } - @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_hash, @events) + let(:cookbook_manifest) do + {"valid1"=> {}, "valid2" => {}} end it "removes unneeded cookbooks" do - @file_cache.should_receive(:find).with(File.join(%w{cookbooks ** *})).and_return(@valid_cached_cb_files + @obsolete_cb_files) - @file_cache.should_receive(:delete).with('cookbooks/old1/recipes/default.rb') - @file_cache.should_receive(:delete).with('cookbooks/old2/recipes/default.rb') - @synchronizer.stub(:cache).and_return(@file_cache) - @synchronizer.clear_obsoleted_cookbooks + valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb} + obsolete_cb_files = %w{cookbooks/old1/recipes/default.rb cookbooks/old2/recipes/default.rb} + expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + obsolete_cb_files) + expect(file_cache).to receive(:delete).with('cookbooks/old1/recipes/default.rb') + expect(file_cache).to receive(:delete).with('cookbooks/old2/recipes/default.rb') + allow(synchronizer).to receive(:cache).and_return(file_cache) + synchronizer.remove_old_cookbooks end end - describe "when syncing cookbooks with the server" do - before do - # Would rather not stub out methods on the test subject, but setting up - # the state is a PITA and tests for this behavior are above. - @synchronizer.stub(:clear_obsoleted_cookbooks) + context "#remove_deleted_files" do + let(:file_cache) { double("Chef::FileCache with files from unused cookbooks") } + + let(:cookbook_manifest) do + {"valid1"=> {}, "valid2" => {}} + end + + it "removes only deleted files" do + valid_cached_cb_files = %w{cookbooks/valid1/recipes/default.rb cookbooks/valid2/recipes/default.rb} + obsolete_cb_files = %w{cookbooks/valid1/recipes/deleted.rb cookbooks/valid2/recipes/deleted.rb} + expect(file_cache).to receive(:find).with(File.join(%w{cookbooks ** {*,.*}})).and_return(valid_cached_cb_files + obsolete_cb_files) + # valid1 is a cookbook in our run_list + expect(synchronizer).to receive(:have_cookbook?).with("valid1").at_least(:once).and_return(true) + # valid2 is a cookbook not in our run_list (we're simulating an override run_list where valid2 needs to be preserved) + expect(synchronizer).to receive(:have_cookbook?).with("valid2").at_least(:once).and_return(false) + expect(file_cache).to receive(:delete).with('cookbooks/valid1/recipes/deleted.rb') + expect(synchronizer).to receive(:cookbook_segment).with("valid1", "recipes").at_least(:once).and_return([ { "path" => "recipes/default.rb" }]) + allow(synchronizer).to receive(:cache).and_return(file_cache) + synchronizer.remove_deleted_files + end + end + + let(:cookbook_a_default_recipe_tempfile) do + double("Tempfile for cookbook_a default.rb recipe", + :path => "/tmp/cookbook_a_recipes_default_rb") + end - @server_api = double("Chef::REST (mock)") - @file_cache = double("Chef::FileCache (mock)") - @synchronizer.stub(:server_api).and_return(@server_api) - @synchronizer.stub(:cache).and_return(@file_cache) + let(:cookbook_a_default_attribute_tempfile) do + double("Tempfile for cookbook_a default.rb attr file", + :path => "/tmp/cookbook_a_attributes_default_rb") + end + let(:cookbook_a_file_default_tempfile) do + double("Tempfile for cookbook_a megaman.conf file", + :path => "/tmp/cookbook_a_file_default_tempfile") + end - @cookbook_a_default_recipe_tempfile = double("Tempfile for cookbook_a default.rb recipe", - :path => "/tmp/cookbook_a_recipes_default_rb") + let(:cookbook_a_template_default_tempfile) do + double("Tempfile for cookbook_a apache.conf.erb template", + :path => "/tmp/cookbook_a_template_default_tempfile") + end - @cookbook_a_default_attribute_tempfile = double("Tempfile for cookbook_a default.rb attr file", - :path => "/tmp/cookbook_a_attributes_default_rb") + def setup_common_files_missing_expectations + # Files are not in the cache: + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/recipes/default.rb"). + and_return(false) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/attributes/default.rb"). + and_return(false) + + # Fetch and copy default.rb recipe + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/abc123', true). + and_return(cookbook_a_default_recipe_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/recipes/default.rb", false). + and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") + + # Fetch and copy default.rb attribute file + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/abc456', true). + and_return(cookbook_a_default_attribute_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/attributes/default.rb", false). + and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") + end + def setup_no_lazy_files_and_templates_missing_expectations + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/files/default/megaman.conf"). + and_return(false) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb"). + and_return(false) + + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/megaman.conf', true). + and_return(cookbook_a_file_default_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/files/default/megaman.conf", false). + and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf") + + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/ffffff', true). + and_return(cookbook_a_template_default_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false). + and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb") + end + + def setup_common_files_chksum_mismatch_expectations + # Files are in the cache: + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/recipes/default.rb"). + and_return(true) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/attributes/default.rb"). + and_return(true) + + # Fetch and copy default.rb recipe + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/abc123', true). + and_return(cookbook_a_default_recipe_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/recipes/default.rb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") + + # Current file has fff000, want abc123 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/recipes/default.rb"). + and_return("fff000") + + # Fetch and copy default.rb attribute file + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/abc456', true). + and_return(cookbook_a_default_attribute_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/attributes/default.rb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") + + # Current file has fff000, want abc456 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/attributes/default.rb"). + and_return("fff000") + end + + def setup_no_lazy_files_and_templates_chksum_mismatch_expectations + # Files are in the cache: + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/files/default/megaman.conf"). + and_return(true) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb"). + and_return(true) + + # Fetch and copy megaman.conf + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/megaman.conf', true). + and_return(cookbook_a_file_default_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/files/default/megaman.conf", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf") + + # Fetch and copy apache2.conf template + expect(server_api).to receive(:get_rest). + with('http://chef.example.com/ffffff', true). + and_return(cookbook_a_template_default_tempfile) + expect(file_cache).to receive(:move_to). + with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb") + + # Current file has fff000 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/default/megaman.conf"). + and_return("fff000") + + # Current file has fff000 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb"). + and_return("fff000") + end + + def setup_common_files_present_expectations + # Files are in the cache: + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/recipes/default.rb"). + and_return(true) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/attributes/default.rb"). + and_return(true) + + # Current file has abc123, want abc123 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/recipes/default.rb"). + and_return("abc123") + + # Current file has abc456, want abc456 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/attributes/default.rb"). + and_return("abc456") + + # :load called twice + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/recipes/default.rb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/attributes/default.rb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") + end + + def setup_no_lazy_files_and_templates_present_expectations + # Files are in the cache: + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/files/default/megaman.conf"). + and_return(true) + expect(file_cache).to receive(:has_key?). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb"). + and_return(true) + + # Current file has abc124, want abc124 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/default/megaman.conf"). + and_return("abc124") + + # Current file has abc125, want abc125 + expect(Chef::CookbookVersion).to receive(:checksum_cookbook_file). + with("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb"). + and_return("abc125") + + # :load called twice + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/files/default/megaman.conf", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf") + expect(file_cache).to receive(:load). + with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false). + twice. + and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb") + end + + describe "when syncing cookbooks with the server" do + let(:server_api) { double("Chef::REST (mock)") } + + let(:file_cache) { double("Chef::FileCache (mock)") } + + before do + # Would rather not stub out methods on the test subject, but setting up + # the state is a PITA and tests for this behavior are above. + allow(synchronizer).to receive(:clear_obsoleted_cookbooks) + allow(synchronizer).to receive(:server_api).and_return(server_api) + allow(synchronizer).to receive(:cache).and_return(file_cache) end context "when the cache does not contain the desired files" do before do - - # Files are not in the cache: - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/recipes/default.rb"). - and_return(false) - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/attributes/default.rb"). - and_return(false) - - # Fetch and copy default.rb recipe - @server_api.should_receive(:get_rest). - with('http://chef.example.com/abc123', true). - and_return(@cookbook_a_default_recipe_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/recipes/default.rb", false). - and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") - - # Fetch and copy default.rb attribute file - @server_api.should_receive(:get_rest). - with('http://chef.example.com/abc456', true). - and_return(@cookbook_a_default_attribute_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/attributes/default.rb", false). - and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") + setup_common_files_missing_expectations end - it "fetches eagerly loaded files" do - @synchronizer.sync_cookbooks - end + context "Chef::Config[:no_lazy_load] is false" do + let(:no_lazy_load) { false } - it "does not fetch templates or cookbook files" do - # Implicitly tested in previous test; this test is just for behavior specification. - @server_api.should_not_receive(:get_rest). - with('http://chef.example.com/ffffff', true) + it "fetches eagerly loaded files" do + synchronizer.sync_cookbooks + end + + it "does not fetch templates or cookbook files" do + # Implicitly tested in previous test; this test is just for behavior specification. + expect(server_api).not_to receive(:get_rest). + with('http://chef.example.com/ffffff', true) - @synchronizer.sync_cookbooks + synchronizer.sync_cookbooks + end end context "Chef::Config[:no_lazy_load] is true" do - before do - Chef::Config[:no_lazy_load] = true - @synchronizer = Chef::CookbookSynchronizer.new(@cookbook_manifest, @events) - @synchronizer.stub(:server_api).and_return(@server_api) - @synchronizer.stub(:cache).and_return(@file_cache) - @synchronizer.stub(:clear_obsoleted_cookbooks) - - @cookbook_a_file_default_tempfile = double("Tempfile for cookbook_a megaman.conf file", - :path => "/tmp/cookbook_a_file_default_tempfile") - @cookbook_a_template_default_tempfile = double("Tempfile for cookbook_a apache.conf.erb template", - :path => "/tmp/cookbook_a_template_default_tempfile") - end + let(:no_lazy_load) { true } - after do - Chef::Config[:no_lazy_load] = false + before do + setup_no_lazy_files_and_templates_missing_expectations end it "fetches templates and cookbook files" do - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/files/default/megaman.conf"). - and_return(false) - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/templates/default/apache2.conf.erb"). - and_return(false) - - @server_api.should_receive(:get_rest). - with('http://chef.example.com/megaman.conf', true). - and_return(@cookbook_a_file_default_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_file_default_tempfile", "cookbooks/cookbook_a/files/default/megaman.conf") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/files/default/megaman.conf", false). - and_return("/file-cache/cookbooks/cookbook_a/default/megaman.conf") - - @server_api.should_receive(:get_rest). - with('http://chef.example.com/ffffff', true). - and_return(@cookbook_a_template_default_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_template_default_tempfile", "cookbooks/cookbook_a/templates/default/apache2.conf.erb") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false). - and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb") - - @synchronizer.sync_cookbooks + synchronizer.sync_cookbooks end end end context "when the cache contains outdated files" do before do - # Files are in the cache: - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/recipes/default.rb"). - and_return(true) - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/attributes/default.rb"). - and_return(true) - - - # Fetch and copy default.rb recipe - @server_api.should_receive(:get_rest). - with('http://chef.example.com/abc123', true). - and_return(@cookbook_a_default_recipe_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_recipes_default_rb", "cookbooks/cookbook_a/recipes/default.rb") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/recipes/default.rb", false). - twice. - and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") - - # Current file has fff000, want abc123 - Chef::CookbookVersion.should_receive(:checksum_cookbook_file). - with("/file-cache/cookbooks/cookbook_a/recipes/default.rb"). - and_return("fff000") - - # Fetch and copy default.rb attribute file - @server_api.should_receive(:get_rest). - with('http://chef.example.com/abc456', true). - and_return(@cookbook_a_default_attribute_tempfile) - @file_cache.should_receive(:move_to). - with("/tmp/cookbook_a_attributes_default_rb", "cookbooks/cookbook_a/attributes/default.rb") - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/attributes/default.rb", false). - twice. - and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") - - # Current file has fff000, want abc456 - Chef::CookbookVersion.should_receive(:checksum_cookbook_file). - with("/file-cache/cookbooks/cookbook_a/attributes/default.rb"). - and_return("fff000") + setup_common_files_chksum_mismatch_expectations end - it "updates the outdated files" do - @synchronizer.sync_cookbooks + context "Chef::Config[:no_lazy_load] is true" do + let(:no_lazy_load) { true } + + before do + setup_no_lazy_files_and_templates_chksum_mismatch_expectations + end + + it "updates the outdated files" do + synchronizer.sync_cookbooks + end + end + + context "Chef::Config[:no_lazy_load] is false" do + let(:no_lazy_load) { false } + + it "updates the outdated files" do + synchronizer.sync_cookbooks + end end end context "when the cache is up to date" do before do - # Files are in the cache: - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/recipes/default.rb"). - and_return(true) - @file_cache.should_receive(:has_key?). - with("cookbooks/cookbook_a/attributes/default.rb"). - and_return(true) - - # Current file has abc123, want abc123 - Chef::CookbookVersion.should_receive(:checksum_cookbook_file). - with("/file-cache/cookbooks/cookbook_a/recipes/default.rb"). - and_return("abc123") - - # Current file has abc456, want abc456 - Chef::CookbookVersion.should_receive(:checksum_cookbook_file). - with("/file-cache/cookbooks/cookbook_a/attributes/default.rb"). - and_return("abc456") - - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/recipes/default.rb", false). - twice. - and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb") - - @file_cache.should_receive(:load). - with("cookbooks/cookbook_a/attributes/default.rb", false). - twice. - and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb") + setup_common_files_present_expectations end - it "does not update files" do - @file_cache.should_not_receive(:move_to) - @server_api.should_not_receive(:get_rest) - @synchronizer.sync_cookbooks + context "Chef::Config[:no_lazy_load] is true" do + let(:no_lazy_load) { true } + + before do + setup_no_lazy_files_and_templates_present_expectations + end + + it "does not update files" do + expect(file_cache).not_to receive(:move_to) + expect(server_api).not_to receive(:get_rest) + synchronizer.sync_cookbooks + end end - end + context "Chef::Config[:no_lazy_load] is false" do + let(:no_lazy_load) { false } + it "does not update files" do + expect(file_cache).not_to receive(:move_to) + expect(server_api).not_to receive(:get_rest) + synchronizer.sync_cookbooks + end + end + end end - end - diff --git a/spec/unit/cookbook_uploader_spec.rb b/spec/unit/cookbook_uploader_spec.rb new file mode 100644 index 0000000000..af25baff13 --- /dev/null +++ b/spec/unit/cookbook_uploader_spec.rb @@ -0,0 +1,160 @@ +# +# Author:: Daniel DeLeo (<dan@getchef.com>) +# Copyright:: Copyright (c) 2014 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 'spec_helper' + +describe Chef::CookbookUploader do + + let(:http_client) { double("Chef::REST") } + + let(:cookbook_loader) do + loader = Chef::CookbookLoader.new(File.join(CHEF_SPEC_DATA, "cookbooks")) + loader.load_cookbooks + loader + end + + let(:apache2_cookbook) { cookbook_loader.cookbooks_by_name["apache2"] } + + let(:java_cookbook) { cookbook_loader.cookbooks_by_name["java"] } + + let(:cookbooks_to_upload) { [apache2_cookbook, java_cookbook] } + + let(:checksums_of_cookbook_files) { apache2_cookbook.checksums.merge(java_cookbook.checksums) } + + let(:checksums_set) do + checksums_of_cookbook_files.keys.inject({}) do |set, cksum| + set[cksum] = nil + set + end + end + + let(:sandbox_commit_uri) { "https://chef.example.org/sandboxes/abc123" } + + let(:uploader) { described_class.new(cookbooks_to_upload, :rest => http_client) } + + it "has a list of cookbooks to upload" do + expect(uploader.cookbooks).to eq(cookbooks_to_upload) + end + + it "creates an HTTP client with default configuration when not initialized with one" do + default_http_client = double("Chef::REST") + expect(Chef::REST).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(default_http_client) + uploader = described_class.new(cookbooks_to_upload) + expect(uploader.rest).to eq(default_http_client) + end + + describe "uploading cookbooks" do + + def url_for(cksum) + "https://storage.example.com/#{cksum}" + end + + let(:sandbox_response) do + sandbox_checksums = cksums_not_on_remote.inject({}) do |cksum_map, cksum| + cksum_map[cksum] = { "needs_upload" => true, "url" => url_for(cksum)} + cksum_map + end + { "checksums" => sandbox_checksums, "uri" => sandbox_commit_uri } + end + + def expect_sandbox_create + expect(http_client).to receive(:post). + with("sandboxes", {:checksums => checksums_set}). + and_return(sandbox_response) + end + + def expect_checksum_upload + checksums_of_cookbook_files.each do |md5, file_path| + next unless cksums_not_on_remote.include?(md5) + + upload_headers = { + "content-type" => "application/x-binary", + "content-md5" => an_instance_of(String), + "accept" => "application/json" + } + + expect(http_client).to receive(:put). + with(url_for(md5), IO.binread(file_path), upload_headers) + + end + end + + def expect_sandbox_commit + expect(http_client).to receive(:put).with(sandbox_commit_uri, {:is_completed => true}) + end + + def expect_cookbook_create + cookbooks_to_upload.each do |cookbook| + + expect(http_client).to receive(:put). + with(cookbook.save_url, cookbook) + + end + end + + context "when no files exist on the server" do + + let(:cksums_not_on_remote) do + checksums_of_cookbook_files.keys + end + + it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do + expect_sandbox_create + expect_checksum_upload + expect_sandbox_commit + expect_cookbook_create + + uploader.upload_cookbooks + end + + end + + context "when some files exist on the server" do + + let(:cksums_not_on_remote) do + checksums_of_cookbook_files.keys[0, 1] + end + + it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do + expect_sandbox_create + expect_checksum_upload + expect_sandbox_commit + expect_cookbook_create + + uploader.upload_cookbooks + end + + end + + context "when all files already exist on the server" do + + let(:cksums_not_on_remote) { [] } + + it "uploads all files in a sandbox transaction, then creates cookbooks on the server" do + expect_sandbox_create + expect_checksum_upload + expect_sandbox_commit + expect_cookbook_create + + uploader.upload_cookbooks + end + + end + end + +end diff --git a/spec/unit/dsl/recipe_spec.rb b/spec/unit/dsl/recipe_spec.rb index 14ee30be44..dfaad0b73e 100644 --- a/spec/unit/dsl/recipe_spec.rb +++ b/spec/unit/dsl/recipe_spec.rb @@ -46,6 +46,18 @@ describe Chef::DSL::Recipe do it "responds to recipe_name" do expect(recipe.recipe_name).to eq(recipe_name) end + + it "responds to shell_out" do + expect(recipe.respond_to?(:shell_out)).to be true + end + + it "responds to shell_out" do + expect(recipe.respond_to?(:shell_out!)).to be true + end + + it "responds to shell_out" do + expect(recipe.respond_to?(:shell_out_with_systems_locale)).to be true + end end context "when included in a class that defines the required interface directly" do diff --git a/spec/unit/formatters/base_spec.rb b/spec/unit/formatters/base_spec.rb new file mode 100644 index 0000000000..6a843ea775 --- /dev/null +++ b/spec/unit/formatters/base_spec.rb @@ -0,0 +1,48 @@ +# +# Author:: Lamont Granquist (<lamont@getchef.com>) +# +# Copyright:: Copyright (c) 2012 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 'spec_helper' + +describe Chef::Formatters::Base do + let(:out) { double("out") } + let(:err) { double("err") } + let(:formatter) { Chef::Formatters::Base.new(out, err) } + + it "starts with an indentation of zero" do + expect(formatter.output.indent).to eql(0) + end + + it "increments it to two correctly" do + formatter.indent_by(2) + expect(formatter.output.indent).to eql(2) + end + + it "increments it and then decrements it corectly" do + formatter.indent_by(2) + formatter.indent_by(-2) + expect(formatter.output.indent).to eql(0) + end + + it "does not allow negative indentation" do + formatter.indent_by(-2) + expect(formatter.output.indent).to eql(0) + end +end + + diff --git a/spec/unit/http/json_input_spec.rb b/spec/unit/http/json_input_spec.rb new file mode 100644 index 0000000000..fbf8f22503 --- /dev/null +++ b/spec/unit/http/json_input_spec.rb @@ -0,0 +1,128 @@ +#-- +# Author:: Daniel DeLeo (<dan@getchef.com>) +# Copyright:: Copyright (c) 2014 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 'spec_helper' +require 'chef/http/json_input' + +describe Chef::HTTP::JSONInput do + + let(:json_encoder) { described_class.new() } + + let(:url) { URI.parse("http://example.com") } + let(:headers) { {} } + + def handle_request + json_encoder.handle_request(http_method, url, headers, data) + end + + it "passes the response unmodified" do + http_response = double("Net::HTTPSuccess") + request = double("Chef::HTTP::HTTPRequest") + return_value = "response body" + + result = json_encoder.handle_response(http_response, request, return_value) + expect(result).to eq([http_response, request, return_value]) + end + + it "doesn't handle streaming responses" do + http_response = double("Net::HTTPSuccess") + expect(json_encoder.stream_response_handler(http_response)).to be nil + end + + it "does nothing for stream completion" do + http_response = double("Net::HTTPSuccess") + request = double("Chef::HTTP::HTTPRequest") + return_value = "response body" + + result = json_encoder.handle_response(http_response, request, return_value) + expect(result).to eq([http_response, request, return_value]) + end + + context "when handling a request with no body" do + + let(:http_method) { :get } + let(:data) { nil } + + it "passes the request unmodified" do + expect(handle_request).to eq([http_method, url, headers, data]) + end + end + + context "when the request should be serialized" do + + let(:http_method) { :put } + let(:data) { {foo: "bar"} } + let(:expected_data) { %q[{"foo":"bar"}] } + + context "and the request has a ruby object as the body and no explicit content-type" do + + it "serializes the body to json" do + # Headers Hash get mutated, so we start by asserting it's empty: + expect(headers).to be_empty + + expect(handle_request).to eq([http_method, url, headers, expected_data]) + + # Now the headers Hash should have json content type: + expect(headers).to have_key("Content-Type") + expect(headers["Content-Type"]).to eq("application/json") + end + end + + context "ant the request has an explicit content type of json" do + + it "serializes the body to json when content-type is all lowercase" do + headers["content-type"] = "application/json" + + expect(handle_request).to eq([http_method, url, headers, expected_data]) + + # Content-Type header should be normalized: + expect(headers.size).to eq(1) + expect(headers).to have_key("Content-Type") + expect(headers["Content-Type"]).to eq("application/json") + end + + end + + end + + context "when handling a request with an explicit content type other than json" do + + let(:http_method) { :put } + let(:data) { "some arbitrary bytes" } + + it "does not serialize the body to json when content type is given as lowercase" do + headers["content-type"] = "application/x-binary" + + expect(handle_request).to eq([http_method, url, headers, data]) + + # not normalized + expect(headers).to eq({"content-type" => "application/x-binary"}) + end + + it "does not serialize the body to json when content type is given in capitalized form" do + headers["Content-Type"] = "application/x-binary" + + expect(handle_request).to eq([http_method, url, headers, data]) + + # not normalized + expect(headers).to eq({"Content-Type" => "application/x-binary"}) + end + + end + +end diff --git a/spec/unit/knife/client_create_spec.rb b/spec/unit/knife/client_create_spec.rb index 897cee8974..59238d69ec 100644 --- a/spec/unit/knife/client_create_spec.rb +++ b/spec/unit/knife/client_create_spec.rb @@ -35,15 +35,15 @@ describe Chef::Knife::ClientCreate do @knife.stub(:edit_data).and_return(@client) @knife.stub(:puts) Chef::ApiClient.stub(:new).and_return(@client) - @stdout = StringIO.new - @knife.ui.stub(:stdout).and_return(@stdout) + @stderr = StringIO.new + @knife.ui.stub(:stderr).and_return(@stderr) end describe "run" do it "should create a new Client" do Chef::ApiClient.should_receive(:new).and_return(@client) @knife.run - @stdout.string.should match /created client.+adam/i + @stderr.string.should match /created client.+adam/i end it "should set the Client name" do diff --git a/spec/unit/knife/configure_client_spec.rb b/spec/unit/knife/configure_client_spec.rb index d101780317..de2a5a41e5 100644 --- a/spec/unit/knife/configure_client_spec.rb +++ b/spec/unit/knife/configure_client_spec.rb @@ -25,8 +25,8 @@ describe Chef::Knife::ConfigureClient do Chef::Config[:validation_client_name] = 'chef-validator' Chef::Config[:validation_key] = '/etc/chef/validation.pem' - @stdout = StringIO.new - @knife.ui.stub(:stdout).and_return(@stdout) + @stderr = StringIO.new + @knife.ui.stub(:stderr).and_return(@stderr) end describe 'run' do @@ -73,11 +73,12 @@ describe Chef::Knife::ConfigureClient do it 'should print information on what is being configured' do FileUtils.stub(:mkdir_p) @knife.run - @stdout.string.should match /creating client configuration/i - @stdout.string.should match /writing client\.rb/i - @stdout.string.should match /writing validation\.pem/i + @stderr.string.should match /creating client configuration/i + @stderr.string.should match /writing client\.rb/i + @stderr.string.should match /writing validation\.pem/i end end end end + diff --git a/spec/unit/knife/cookbook_delete_spec.rb b/spec/unit/knife/cookbook_delete_spec.rb index f4ba46f513..53b120be71 100644 --- a/spec/unit/knife/cookbook_delete_spec.rb +++ b/spec/unit/knife/cookbook_delete_spec.rb @@ -204,7 +204,7 @@ describe Chef::Knife::CookbookDelete do it 'should output that the cookbook was deleted' do @knife.stub(:delete_request) @knife.delete_version_without_confirmation('1.0.0') - @stdout.string.should match /deleted cookbook\[foobar\]\[1.0.0\]/im + @stderr.string.should match /deleted cookbook\[foobar\]\[1.0.0\]/im end describe 'with --print-after' do diff --git a/spec/unit/knife/cookbook_download_spec.rb b/spec/unit/knife/cookbook_download_spec.rb index efab98f646..6f40a3396b 100644 --- a/spec/unit/knife/cookbook_download_spec.rb +++ b/spec/unit/knife/cookbook_download_spec.rb @@ -21,8 +21,8 @@ require 'spec_helper' describe Chef::Knife::CookbookDownload do before(:each) do @knife = Chef::Knife::CookbookDownload.new - @stdout = StringIO.new - @knife.ui.stub(:stdout).and_return(@stdout) + @stderr = StringIO.new + @knife.ui.stub(:stderr).and_return(@stderr) end describe 'run' do @@ -121,10 +121,10 @@ describe Chef::Knife::CookbookDownload do File.should_receive(:exists?).with('/var/tmp/chef/foobar-1.0.0').and_return(false) @knife.run ['attributes', 'recipes', 'templates'].each do |segment| - @stdout.string.should match /downloading #{segment}/im + @stderr.string.should match /downloading #{segment}/im end - @stdout.string.should match /downloading foobar cookbook version 1\.0\.0/im - @stdout.string.should match /cookbook downloaded to \/var\/tmp\/chef\/foobar-1\.0\.0/im + @stderr.string.should match /downloading foobar cookbook version 1\.0\.0/im + @stderr.string.should match /cookbook downloaded to \/var\/tmp\/chef\/foobar-1\.0\.0/im end describe 'with -f or --force' do diff --git a/spec/unit/knife/cookbook_metadata_spec.rb b/spec/unit/knife/cookbook_metadata_spec.rb index 26ff43829c..1d6568739c 100644 --- a/spec/unit/knife/cookbook_metadata_spec.rb +++ b/spec/unit/knife/cookbook_metadata_spec.rb @@ -119,7 +119,7 @@ describe Chef::Knife::CookbookMetadata do Chef::JSONCompat.should_receive(:to_json_pretty).with(@metadata_mock). and_return(@json_data) @knife.generate_metadata_from_file('foobar', "#{@cookbook_dir}/foobar/metadata.rb") - @stdout.string.should match /generating metadata for foobar from #{@cookbook_dir}\/foobar\/metadata\.rb/im + @stderr.string.should match /generating metadata for foobar from #{@cookbook_dir}\/foobar\/metadata\.rb/im end { Chef::Exceptions::ObsoleteDependencySyntax => 'obsolote dependency', diff --git a/spec/unit/knife/cookbook_site_download_spec.rb b/spec/unit/knife/cookbook_site_download_spec.rb index faf58f7bc7..7cd71c2211 100644 --- a/spec/unit/knife/cookbook_site_download_spec.rb +++ b/spec/unit/knife/cookbook_site_download_spec.rb @@ -25,7 +25,7 @@ describe Chef::Knife::CookbookSiteDownload do @knife = Chef::Knife::CookbookSiteDownload.new @knife.name_args = ['apache2'] @noauth_rest = double('no auth rest') - @stdout = StringIO.new + @stderr = StringIO.new @cookbook_api_url = 'http://cookbooks.opscode.com/api/v1/cookbooks' @version = '1.0.2' @version_us = @version.gsub '.', '_' @@ -33,7 +33,7 @@ describe Chef::Knife::CookbookSiteDownload do 'latest_version' => "#{@cookbook_api_url}/apache2/versions/#{@version_us}", 'replacement' => 'other_apache2' } - @knife.ui.stub(:stdout).and_return(@stdout) + @knife.ui.stub(:stderr).and_return(@stderr) @knife.stub(:noauth_rest).and_return(@noauth_rest) @noauth_rest.should_receive(:get_rest). with("#{@cookbook_api_url}/apache2"). @@ -85,8 +85,8 @@ describe Chef::Knife::CookbookSiteDownload do with(/.+deprecated.+replaced by other_apache2.+/i) FileUtils.should_receive(:cp).with(@temp_file.path, @file) @knife.run - @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i - @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i + @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i + @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i end end @@ -94,8 +94,8 @@ describe Chef::Knife::CookbookSiteDownload do it 'should download the latest version' do FileUtils.should_receive(:cp).with(@temp_file.path, @file) @knife.run - @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i - @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i + @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i + @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i end context 'with -f or --file' do @@ -107,8 +107,8 @@ describe Chef::Knife::CookbookSiteDownload do it 'should download the cookbook to the desired file' do @knife.run - @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i - @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i + @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i + @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i end end @@ -139,8 +139,8 @@ describe Chef::Knife::CookbookSiteDownload do and_return(@temp_file) FileUtils.should_receive(:cp).with(@temp_file.path, @file) @knife.run - @stdout.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i - @stdout.string.should match /cookbook save.+#{Regexp.escape(@file)}/i + @stderr.string.should match /downloading apache2.+version.+#{Regexp.escape(@version)}/i + @stderr.string.should match /cookbook save.+#{Regexp.escape(@file)}/i end end diff --git a/spec/unit/knife/cookbook_site_share_spec.rb b/spec/unit/knife/cookbook_site_share_spec.rb index 28b2a509fd..a46783274b 100644 --- a/spec/unit/knife/cookbook_site_share_spec.rb +++ b/spec/unit/knife/cookbook_site_share_spec.rb @@ -34,7 +34,7 @@ describe Chef::Knife::CookbookSiteShare do @cookbook_loader.stub(:[]).and_return(@cookbook) Chef::CookbookLoader.stub(:new).and_return(@cookbook_loader) - @cookbook_uploader = Chef::CookbookUploader.new('herpderp', File.join(CHEF_SPEC_DATA, 'cookbooks'), :rest => "norest") + @cookbook_uploader = Chef::CookbookUploader.new('herpderp', :rest => "norest") Chef::CookbookUploader.stub(:new).and_return(@cookbook_uploader) @cookbook_uploader.stub(:validate_cookbooks).and_return(true) Chef::CookbookSiteStreamingUploader.stub(:create_build_dir).and_return(Dir.mktmpdir) @@ -77,7 +77,7 @@ describe Chef::Knife::CookbookSiteShare do it 'should make a tarball of the cookbook' do @knife.should_receive(:shell_out!) do |args| - args.to_s.should match /tar -czf/ + args.to_s.should match(/tar -czf/) end @knife.run end diff --git a/spec/unit/knife/cookbook_upload_spec.rb b/spec/unit/knife/cookbook_upload_spec.rb index 6a99a80459..e5c9a40cf1 100644 --- a/spec/unit/knife/cookbook_upload_spec.rb +++ b/spec/unit/knife/cookbook_upload_spec.rb @@ -61,8 +61,9 @@ describe Chef::Knife::CookbookUpload do test_cookbook = Chef::CookbookVersion.new('test_cookbook', '/tmp/blah') cookbook_loader.stub(:each).and_yield("test_cookbook", test_cookbook) cookbook_loader.stub(:cookbook_names).and_return(["test_cookbook"]) - Chef::CookbookUploader.should_receive(:new).with( kind_of(Array), kind_of(Array), - {:force=>nil, :concurrency => 3}).and_return(double("Chef::CookbookUploader", :upload_cookbooks=> true)) + Chef::CookbookUploader.should_receive(:new). + with( kind_of(Array), { :force => nil, :concurrency => 3}). + and_return(double("Chef::CookbookUploader", :upload_cookbooks=> true)) knife.run end end diff --git a/spec/unit/knife/tag_create_spec.rb b/spec/unit/knife/tag_create_spec.rb index 82e3ad68cd..bafea8d268 100644 --- a/spec/unit/knife/tag_create_spec.rb +++ b/spec/unit/knife/tag_create_spec.rb @@ -9,15 +9,15 @@ describe Chef::Knife::TagCreate do @node = Chef::Node.new @node.stub :save Chef::Node.stub(:load).and_return @node - @stdout = StringIO.new - @knife.ui.stub(:stdout).and_return(@stdout) + @stderr = StringIO.new + @knife.ui.stub(:stderr).and_return(@stderr) end describe "run" do it "can create tags on a node" do @knife.run @node.tags.should == ["happytag"] - @stdout.string.should match /created tags happytag.+node webmonkey.example.com/i + @stderr.string.should match /created tags happytag.+node webmonkey.example.com/i end end end diff --git a/spec/unit/knife/tag_delete_spec.rb b/spec/unit/knife/tag_delete_spec.rb index 67e3dd3ff0..514228f0a2 100644 --- a/spec/unit/knife/tag_delete_spec.rb +++ b/spec/unit/knife/tag_delete_spec.rb @@ -10,8 +10,8 @@ describe Chef::Knife::TagDelete do @node.stub :save @node.tags << "sadtag" << "happytag" Chef::Node.stub(:load).and_return @node - @stdout = StringIO.new - @knife.ui.stub(:stdout).and_return(@stdout) + @stderr = StringIO.new + @knife.ui.stub(:stderr).and_return(@stderr) end describe "run" do @@ -19,7 +19,7 @@ describe Chef::Knife::TagDelete do @node.tags.should == ["sadtag", "happytag"] @knife.run @node.tags.should == ["happytag"] - @stdout.string.should match /deleted.+sadtag/i + @stderr.string.should match /deleted.+sadtag/i end end end diff --git a/spec/unit/knife/user_create_spec.rb b/spec/unit/knife/user_create_spec.rb index 039d4659b0..58ef868053 100644 --- a/spec/unit/knife/user_create_spec.rb +++ b/spec/unit/knife/user_create_spec.rb @@ -46,7 +46,7 @@ describe Chef::Knife::UserCreate do Chef::User.should_receive(:new).and_return(@user) @user.should_receive(:create) @knife.run - @stdout.string.should match /created user.+a_user/i + @stderr.string.should match /created user.+a_user/i end it "sets the password" do diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb index 52784741d7..70b60a2f96 100644 --- a/spec/unit/knife_spec.rb +++ b/spec/unit/knife_spec.rb @@ -41,7 +41,7 @@ describe Chef::Knife do Chef::Log.stub(level_sym) end Chef::Knife.stub(:puts) - @stdout = StringIO.new + @stderr = StringIO.new end describe "selecting a config file" do @@ -241,7 +241,7 @@ describe Chef::Knife do end it "exits if no subcommand matches the CLI args" do - Chef::Knife.ui.stub(:stdout).and_return(@stdout) + Chef::Knife.ui.stub(:stderr).and_return(@stderr) Chef::Knife.ui.should_receive(:fatal) lambda {Chef::Knife.run(%w{fuuu uuuu fuuuu})}.should raise_error(SystemExit) { |e| e.status.should_not == 0 } end @@ -326,7 +326,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPServerException.new("401 Unauthorized", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(/ERROR: Failed to authenticate to/) - @stdout.string.should match(/Response: y u no syncronize your clock\?/) + @stderr.string.should match(/Response: y u no syncronize your clock\?/) end it "formats 403s nicely" do @@ -337,7 +337,7 @@ describe Chef::Knife do @knife.stub(:username).and_return("sadpanda") @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action]) - @stdout.string.should match(%r[Response: y u no administrator]) + @stderr.string.should match(%r[Response: y u no administrator]) end it "formats 400s nicely" do @@ -347,7 +347,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPServerException.new("400 Bad Request", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: The data in your request was invalid]) - @stdout.string.should match(%r[Response: y u search wrong]) + @stderr.string.should match(%r[Response: y u search wrong]) end it "formats 404s nicely" do @@ -357,7 +357,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPServerException.new("404 Not Found", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: The object you are looking for could not be found]) - @stdout.string.should match(%r[Response: nothing to see here]) + @stderr.string.should match(%r[Response: nothing to see here]) end it "formats 500s nicely" do @@ -367,7 +367,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPFatalError.new("500 Internal Server Error", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: internal server error]) - @stdout.string.should match(%r[Response: sad trombone]) + @stderr.string.should match(%r[Response: sad trombone]) end it "formats 502s nicely" do @@ -377,7 +377,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPFatalError.new("502 Bad Gateway", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: bad gateway]) - @stdout.string.should match(%r[Response: sadder trombone]) + @stderr.string.should match(%r[Response: sadder trombone]) end it "formats 503s nicely" do @@ -387,7 +387,7 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPFatalError.new("503 Service Unavailable", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: Service temporarily unavailable]) - @stdout.string.should match(%r[Response: saddest trombone]) + @stderr.string.should match(%r[Response: saddest trombone]) end it "formats other HTTP errors nicely" do @@ -397,15 +397,15 @@ describe Chef::Knife do @knife.stub(:run).and_raise(Net::HTTPServerException.new("402 Payment Required", response)) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: Payment Required]) - @stdout.string.should match(%r[Response: nobugfixtillyoubuy]) + @stderr.string.should match(%r[Response: nobugfixtillyoubuy]) end it "formats NameError and NoMethodError nicely" do @knife.stub(:run).and_raise(NameError.new("Undefined constant FUUU")) @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: knife encountered an unexpected error]) - @stdout.string.should match(%r[This may be a bug in the 'knife' knife command or plugin]) - @stdout.string.should match(%r[Exception: NameError: Undefined constant FUUU]) + @stderr.string.should match(%r[This may be a bug in the 'knife' knife command or plugin]) + @stderr.string.should match(%r[Exception: NameError: Undefined constant FUUU]) end it "formats missing private key errors nicely" do @@ -413,7 +413,7 @@ describe Chef::Knife do @knife.stub(:api_key).and_return("/home/root/.chef/no-key-here.pem") @knife.run_with_pretty_exceptions @stderr.string.should match(%r[ERROR: Your private key could not be loaded from /home/root/.chef/no-key-here.pem]) - @stdout.string.should match(%r[Check your configuration file and ensure that your private key is readable]) + @stderr.string.should match(%r[Check your configuration file and ensure that your private key is readable]) end it "formats connection refused errors nicely" do @@ -423,7 +423,7 @@ describe Chef::Knife do # *nix = Errno::ECONNREFUSED: Connection refused # win32: Errno::ECONNREFUSED: No connection could be made because the target machine actively refused it. @stderr.string.should match(%r[ERROR: Network Error: .* - y u no shut up]) - @stdout.string.should match(%r[Check your knife configuration and network settings]) + @stderr.string.should match(%r[Check your knife configuration and network settings]) end end diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb index 9a775f2dff..960aff3c36 100644 --- a/spec/unit/lwrp_spec.rb +++ b/spec/unit/lwrp_spec.rb @@ -180,6 +180,19 @@ describe "LWRP" do end end + describe "when #default_action is an array" do + let(:lwrp) do + Class.new(Chef::Resource::LWRPBase) do + actions :eat, :sleep + default_action [:eat, :sleep] + end + end + + it "returns the array of default actions" do + expect(lwrp.default_action).to eq([:eat, :sleep]) + end + end + describe "when inheriting from LWRPBase" do let(:parent) do Class.new(Chef::Resource::LWRPBase) do diff --git a/spec/unit/mixin/template_spec.rb b/spec/unit/mixin/template_spec.rb index 3aa0b9ba22..63fa81782e 100644 --- a/spec/unit/mixin/template_spec.rb +++ b/spec/unit/mixin/template_spec.rb @@ -76,7 +76,7 @@ describe Chef::Mixin::Template, "render_template" do describe "with a template resource" do before :each do @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo) @node = Chef::Node.new cl = Chef::CookbookLoader.new(@cookbook_repo) diff --git a/spec/unit/provider/http_request_spec.rb b/spec/unit/provider/http_request_spec.rb index 605287fcc3..3077685b97 100644 --- a/spec/unit/provider/http_request_spec.rb +++ b/spec/unit/provider/http_request_spec.rb @@ -53,13 +53,13 @@ describe Chef::Provider::HttpRequest do it "should inflate a message block at runtime" do @new_resource.message { "return" } - @http.should_receive(:get).with("http://www.opscode.com/?message=return", {}) + @http.should_receive(:get).with("http://www.opscode.com/", {}) @provider.run_action(:get) @new_resource.should be_updated end it "should run a GET request" do - @http.should_receive(:get).with("http://www.opscode.com/?message=is cool", {}) + @http.should_receive(:get).with("http://www.opscode.com/", {}) @provider.run_action(:get) @new_resource.should be_updated end @@ -112,25 +112,25 @@ describe Chef::Provider::HttpRequest do it "should inflate a message block at runtime" do @new_resource.message { "return" } - @http.should_receive(:head).with("http://www.opscode.com/?message=return", {}).and_return(nil) + @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil) @provider.run_action(:head) @new_resource.should be_updated end it "should run a HEAD request" do - @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return(nil) + @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil) @provider.run_action(:head) @new_resource.should be_updated end it "should update a HEAD request with empty string response body (CHEF-4762)" do - @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return("") + @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return("") @provider.run_action(:head) @new_resource.should be_updated end it "should update a HEAD request with nil response body (CHEF-4762)" do - @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {}).and_return(nil) + @http.should_receive(:head).with("http://www.opscode.com/", {}).and_return(nil) @provider.run_action(:head) @new_resource.should be_updated end @@ -138,14 +138,14 @@ describe Chef::Provider::HttpRequest do it "should not update a HEAD request if a not modified response (CHEF-4762)" do if_modified_since = File.mtime(__FILE__).httpdate @new_resource.headers "If-Modified-Since" => if_modified_since - @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", {"If-Modified-Since" => if_modified_since}).and_return(false) + @http.should_receive(:head).with("http://www.opscode.com/", {"If-Modified-Since" => if_modified_since}).and_return(false) @provider.run_action(:head) @new_resource.should_not be_updated end it "should run a HEAD request with If-Modified-Since header" do @new_resource.headers "If-Modified-Since" => File.mtime(__FILE__).httpdate - @http.should_receive(:head).with("http://www.opscode.com/?message=is cool", @new_resource.headers) + @http.should_receive(:head).with("http://www.opscode.com/", @new_resource.headers) @provider.run_action(:head) end diff --git a/spec/unit/provider/log_spec.rb b/spec/unit/provider/log_spec.rb index 8f411e461a..f6ff526dd4 100644 --- a/spec/unit/provider/log_spec.rb +++ b/spec/unit/provider/log_spec.rb @@ -78,22 +78,4 @@ describe Chef::Provider::Log::ChefLog do @provider.action_write end - it "should not update the resource if the message was not written to the log" do - Chef::Log.level = :fatal - @new_resource = Chef::Resource::Log.new(@log_str) - @new_resource.level :info - @provider = Chef::Provider::Log::ChefLog.new(@new_resource, @run_context) - @provider.action_write - @new_resource.updated.should be_false - end - - it "should update the resource if the message has been written to the log" do - Chef::Log.level = :debug - @new_resource = Chef::Resource::Log.new(@log_str) - @new_resource.level :info - @provider = Chef::Provider::Log::ChefLog.new(@new_resource, @run_context) - @provider.action_write - @new_resource.updated.should be_true - end - end diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb index 33b4f8186a..375a0d0646 100644 --- a/spec/unit/provider/package_spec.rb +++ b/spec/unit/provider/package_spec.rb @@ -339,7 +339,7 @@ describe Chef::Provider::Package do describe "when given a response file" do before(:each) do @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo) @node = Chef::Node.new cl = Chef::CookbookLoader.new(@cookbook_repo) diff --git a/spec/unit/provider/remote_directory_spec.rb b/spec/unit/provider/remote_directory_spec.rb index d3f1438f0f..b986e2c8ad 100644 --- a/spec/unit/provider/remote_directory_spec.rb +++ b/spec/unit/provider/remote_directory_spec.rb @@ -35,7 +35,7 @@ describe Chef::Provider::RemoteDirectory do @resource.cookbook('openldap') @cookbook_repo = ::File.expand_path(::File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo) @node = Chef::Node.new cl = Chef::CookbookLoader.new(@cookbook_repo) diff --git a/spec/unit/provider/template/content_spec.rb b/spec/unit/provider/template/content_spec.rb index dfc5d21c2a..b419e70519 100644 --- a/spec/unit/provider/template/content_spec.rb +++ b/spec/unit/provider/template/content_spec.rb @@ -36,7 +36,7 @@ describe Chef::Provider::Template::Content do let(:run_context) do cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) } + Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo) cl = Chef::CookbookLoader.new(cookbook_repo) cl.load_cookbooks cookbook_collection = Chef::CookbookCollection.new(cl) diff --git a/spec/unit/provider_spec.rb b/spec/unit/provider_spec.rb index 363649ec46..9b89fc1888 100644 --- a/spec/unit/provider_spec.rb +++ b/spec/unit/provider_spec.rb @@ -61,6 +61,18 @@ describe Chef::Provider do @provider = Chef::Provider.new(@resource, @run_context) end + it "should mixin shell_out" do + expect(@provider.respond_to?(:shell_out)).to be true + end + + it "should mixin shell_out!" do + expect(@provider.respond_to?(:shell_out!)).to be true + end + + it "should mixin shell_out_with_systems_locale" do + expect(@provider.respond_to?(:shell_out_with_systems_locale)).to be true + end + it "should store the resource passed to new as new_resource" do @provider.new_resource.should eql(@resource) end diff --git a/spec/unit/shell/shell_session_spec.rb b/spec/unit/shell/shell_session_spec.rb index 92a2e5d538..f49c9fc805 100644 --- a/spec/unit/shell/shell_session_spec.rb +++ b/spec/unit/shell/shell_session_spec.rb @@ -50,6 +50,7 @@ end describe Shell::ClientSession do before do Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new('shell::override')] } + @chef_rest = double("Chef::REST") @session = Shell::ClientSession.instance @node = Chef::Node.build("foo") @session.node = @node @@ -66,6 +67,7 @@ describe Shell::ClientSession do @expansion = Chef::RunList::RunListExpansion.new(@node.chef_environment, []) @node.run_list.should_receive(:expand).with(@node.chef_environment).and_return(@expansion) + Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url]).and_return(@chef_rest) @session.rebuild_context end |