summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2012-12-21 12:15:38 -0800
committerdanielsdeleo <dan@opscode.com>2012-12-21 12:15:38 -0800
commit5c17ea2b59d87f806cc28abce594aee061ac0e69 (patch)
tree0c686878aa3f56727e8e801b56e66b6ffd3d4da2
parenteed92c71356f44afc03c575ca5aadff8023cb334 (diff)
parent72cf70f4495009e0f6fc8ab7e23b4eb8232d371b (diff)
downloadchef-5c17ea2b59d87f806cc28abce594aee061ac0e69.tar.gz
Merge branch 'CHEF-3715'
-rw-r--r--chef.gemspec3
-rw-r--r--distro/common/markdown/man1/knife.mkd11
-rw-r--r--lib/chef/checksum_cache.rb190
-rw-r--r--lib/chef/config.rb20
-rw-r--r--lib/chef/cookbook/syntax_check.rb75
-rw-r--r--lib/chef/cookbook_uploader.rb2
-rw-r--r--lib/chef/cookbook_version.rb2
-rw-r--r--lib/chef/digester.rb73
-rw-r--r--lib/chef/knife/configure.rb3
-rw-r--r--lib/chef/knife/cookbook_test.rb1
-rw-r--r--lib/chef/mixin/checksum.rb6
-rw-r--r--lib/chef/monkey_patches/moneta.rb50
-rw-r--r--spec/support/chef_helpers.rb2
-rw-r--r--spec/unit/checksum_cache_spec.rb209
-rw-r--r--spec/unit/cookbook/syntax_check_spec.rb157
-rw-r--r--spec/unit/digester_spec.rb50
-rw-r--r--spec/unit/mixin/checksum_spec.rb4
-rw-r--r--spec/unit/provider/file_spec.rb59
-rw-r--r--spec/unit/provider/template_spec.rb1
19 files changed, 288 insertions, 630 deletions
diff --git a/chef.gemspec b/chef.gemspec
index fcf5d2b8ec..9de2822270 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -26,9 +26,8 @@ Gem::Specification.new do |s|
s.add_dependency "net-ssh-multi", "~> 1.1.0"
# CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not.
s.add_dependency "highline", ">= 1.6.9"
- %w{erubis moneta}.each { |gem| s.add_dependency gem }
+ s.add_dependency "erubis"
- # development_dependency thin: eventmachine 0.12.10 doesn't support Ruby 1.9 on Windows
%w(rdoc sdoc ronn rake rack rspec_junit_formatter).each { |gem| s.add_development_dependency gem }
%w(rspec-core rspec-expectations rspec-mocks).each { |gem| s.add_development_dependency gem, "~> 2.8.0" }
diff --git a/distro/common/markdown/man1/knife.mkd b/distro/common/markdown/man1/knife.mkd
index 054e220cf9..8c97cc97e1 100644
--- a/distro/common/markdown/man1/knife.mkd
+++ b/distro/common/markdown/man1/knife.mkd
@@ -98,14 +98,9 @@ If the config file exists, knife uses these settings for __GENERAL OPTIONS__ def
* `chef_server_url`:
URL of the Chef server. Corresponds to the `-s` or `--server-url`
option. This is requested from the user when running this sub-command.
- * `cache_type`:
- The type of cache to use. Default is BasicFile. This can be any type of
- Cache that moneta supports: BasicFile, Berkeley, Couch, DataMapper,
- File, LMC, Memcache, Memory, MongoDB, Redis, Rufus, S3, SDBM, Tyrant,
- Xattr, YAML.
- * `cache_options`:
- Specifies various options to use for caching. These options are
- dependent on the `cache_type`.
+ * `syntax_check_cache_path`:
+ Specifies the path to a directory where knife caches information
+ about files that it has syntax checked.
* `validation_client_name`:
Specifies the name of the client used to validate new clients.
* `validation_key`:
diff --git a/lib/chef/checksum_cache.rb b/lib/chef/checksum_cache.rb
deleted file mode 100644
index 6db7115a56..0000000000
--- a/lib/chef/checksum_cache.rb
+++ /dev/null
@@ -1,190 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Opscode, Inc.
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# 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 'set'
-require 'fileutils'
-require 'chef/log'
-require 'chef/config'
-require 'chef/client'
-require 'chef/mixin/convert_to_class_name'
-require 'singleton'
-require 'moneta'
-
-class Chef
- class ChecksumCache
- include Chef::Mixin::ConvertToClassName
- include ::Singleton
-
- attr_reader :moneta
-
- def initialize(*args)
- self.reset!(*args)
- end
-
- def reset!(backend=nil, options=nil)
- backend ||= Chef::Config[:cache_type]
- options ||= Chef::Config[:cache_options]
-
- begin
- require "moneta/#{convert_to_snake_case(backend, 'Moneta')}"
- require 'chef/monkey_patches/moneta'
- rescue LoadError => e
- Chef::Log.fatal("Could not load Moneta back end #{backend.inspect}")
- raise e
- end
-
- @moneta = Moneta.const_get(backend).new(options)
- end
-
- def self.reset_cache_validity
- @valid_cached_checksums = nil
- end
-
- Chef::Client.when_run_starts do |run_status|
- reset_cache_validity
- end
-
- def self.valid_cached_checksums
- @valid_cached_checksums ||= Set.new
- end
-
- def self.validate_checksum(checksum_key)
- valid_cached_checksums << checksum_key
- end
-
- def self.all_cached_checksums
- all_checksums_with_filenames = {}
-
- Dir[File.join(Chef::Config[:cache_options][:path], '*')].each do |cksum_file|
- all_checksums_with_filenames[File.basename(cksum_file)] = cksum_file
- end
- all_checksums_with_filenames
- end
-
- def self.cleanup_checksum_cache
- Chef::Log.debug("Cleaning the checksum cache")
- if (Chef::Config[:cache_type].to_s == "BasicFile")
- all_cached_checksums.each do |cache_key, cksum_cache_file|
- unless valid_cached_checksums.include?(cache_key)
- remove_unused_checksum(cksum_cache_file)
- end
- end
- end
- end
-
- Chef::Client.when_run_completes_successfully do |run_status|
- cleanup_checksum_cache
- end
-
- def self.remove_unused_checksum(checksum_file)
- Chef::Log.debug("Removing unused checksum cache file #{checksum_file}")
- FileUtils.rm(checksum_file)
- end
-
- def self.checksum_for_file(*args)
- instance.checksum_for_file(*args)
- end
-
- def validate_checksum(*args)
- self.class.validate_checksum(*args)
- end
-
- def checksum_for_file(file, key=nil)
- key ||= generate_key(file)
- fstat = File.stat(file)
- lookup_checksum(key, fstat) || generate_checksum(key, file, fstat)
- end
-
- def lookup_checksum(key, fstat)
- cached = fetch(key)
- if cached && file_unchanged?(cached, fstat)
- validate_checksum(key)
- cached["checksum"]
- else
- nil
- end
- end
-
- def generate_checksum(key, file, fstat)
- checksum = checksum_file(file, Digest::SHA256.new)
- moneta.store(key, {"mtime" => fstat.mtime.to_f, "checksum" => checksum})
- validate_checksum(key)
- checksum
- end
-
- def generate_key(file, group="chef")
- "#{group}-file-#{file.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
- end
-
- def self.generate_md5_checksum_for_file(*args)
- instance.generate_md5_checksum_for_file(*args)
- end
-
- def generate_md5_checksum_for_file(file)
- checksum_file(file, Digest::MD5.new)
- end
-
- def generate_md5_checksum(io)
- checksum_io(io, Digest::MD5.new)
- end
-
- private
-
- def fetch(key)
- @moneta.fetch(key)
- rescue ArgumentError => e
- Log.warn "Error loading cached checksum for key #{key.inspect}"
- Log.warn(e)
- repair_checksum_cache
- nil
- end
-
- def repair_checksum_cache
- Chef::Log.info("Removing invalid checksum cache files")
- Dir["#{Chef::Config[:cache_options][:path]}/*"].each do |file_path|
- File.unlink(file_path) unless File.size?(file_path)
- end
- end
-
- def file_unchanged?(cached, fstat)
- cached["mtime"].to_f == fstat.mtime.to_f
- end
-
- def checksum_file(file, digest)
- File.open(file, 'rb') { |f| checksum_io(f, digest) }
- end
-
- def checksum_io(io, digest)
- while chunk = io.read(1024 * 8)
- digest.update(chunk)
- end
- digest.hexdigest
- end
-
- end
-end
-
-module Moneta
- module Defaults
- def default
- nil
- end
- end
-end
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index 85dce44474..d05692ddc8 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -48,9 +48,6 @@ class Chef
end
def self.platform_specific_path(path)
- #10.times { puts "* " * 40}
- #pp caller
-
if RUBY_PLATFORM =~ /mswin|mingw|windows/
# turns /etc/chef/client.rb into C:/chef/client.rb
system_drive = ENV['SYSTEMDRIVE'] ? ENV['SYSTEMDRIVE'] : ""
@@ -309,10 +306,19 @@ class Chef
# Start handlers
start_handlers []
- # Checksum Cache
- # Uses Moneta on the back-end
- cache_type "BasicFile"
- cache_options({ :path => platform_specific_path("/var/chef/cache/checksums"), :skip_expires => true })
+ # Syntax Check Cache. Knife keeps track of files that is has already syntax
+ # checked by storing files in this directory. `syntax_check_cache_path` is
+ # the new (and preferred) configuration setting. If not set, knife will
+ # fall back to using cache_options[:path].
+ #
+ # Because many users will have knife configs with cache_options (generated
+ # by `knife configure`), the default for now is to *not* set
+ # syntax_check_cache_path, and thus fallback to cache_options[:path]. We
+ # leave that value to the same default as was previously set.
+ syntax_check_cache_path nil
+
+ # Deprecated:
+ cache_options({ :path => platform_specific_path("/var/chef/cache/checksums") })
# Set to false to silence Chef 11 deprecation warnings:
chef11_deprecation_warnings true
diff --git a/lib/chef/cookbook/syntax_check.rb b/lib/chef/cookbook/syntax_check.rb
index bf7c45e252..40ba070796 100644
--- a/lib/chef/cookbook/syntax_check.rb
+++ b/lib/chef/cookbook/syntax_check.rb
@@ -16,8 +16,8 @@
# limitations under the License.
#
-require 'chef/checksum_cache'
require 'chef/mixin/shell_out'
+require 'chef/mixin/checksum'
class Chef
class Cookbook
@@ -25,10 +25,65 @@ class Chef
# Encapsulates the process of validating the ruby syntax of files in Chef
# cookbooks.
class SyntaxCheck
+
+ # == Chef::Cookbook::SyntaxCheck::PersistentSet
+ # Implements set behavior with disk-based persistence. Objects in the set
+ # are expected to be strings containing only characters that are valid in
+ # filenames.
+ #
+ # This class is used to track which files have been syntax checked so
+ # that known good files are not rechecked.
+ class PersistentSet
+
+ attr_reader :cache_path
+
+ # Create a new PersistentSet. Values in the set are persisted by
+ # creating a file in the +cache_path+ directory. If not given, the
+ # value of Chef::Config[:syntax_check_cache_path] is used; if that
+ # value is not configured, the value of
+ # Chef::Config[:cache_options][:path] is used.
+ #--
+ # history: prior to Chef 11, the cache implementation was based on
+ # moneta and configured via cache_options[:path]. Knife configs
+ # generated with Chef 11 will have `syntax_check_cache_path`, but older
+ # configs will have `cache_options[:path]`. `cache_options` is marked
+ # deprecated in chef/config.rb but doesn't currently trigger a warning.
+ # See also: CHEF-3715
+ def initialize(cache_path=nil)
+ @cache_path = cache_path || Chef::Config[:syntax_check_cache_path] || Chef::Config[:cache_options][:path]
+ @cache_path_created = false
+ end
+
+ # Adds +value+ to the set's collection.
+ def add(value)
+ ensure_cache_path_created
+ FileUtils.touch(File.join(cache_path, value))
+ end
+
+ # Returns true if the set includes +value+
+ def include?(value)
+ File.exist?(File.join(cache_path, value))
+ end
+
+ private
+
+ def ensure_cache_path_created
+ return true if @cache_path_created
+ FileUtils.mkdir_p(cache_path)
+ @cache_path_created = true
+ end
+
+ end
+
include Chef::Mixin::ShellOut
+ include Chef::Mixin::Checksum
attr_reader :cookbook_path
+ # A PersistentSet object that tracks which files have already been
+ # validated.
+ attr_reader :validated_files
+
# Creates a new SyntaxCheck given the +cookbook_name+ and a +cookbook_path+.
# If no +cookbook_path+ is given, +Chef::Config.cookbook_path+ is used.
def self.for_cookbook(cookbook_name, cookbook_path=nil)
@@ -44,10 +99,7 @@ class Chef
# cookbook_path::: the (on disk) path to the cookbook
def initialize(cookbook_path)
@cookbook_path = cookbook_path
- end
-
- def cache
- Chef::ChecksumCache.instance
+ @validated_files = PersistentSet.new
end
def ruby_files
@@ -81,16 +133,11 @@ class Chef
end
def validated?(file)
- !!cache.lookup_checksum(cache_key(file), File.stat(file))
+ validated_files.include?(checksum(file))
end
def validated(file)
- cache.generate_checksum(cache_key(file), file, File.stat(file))
- end
-
- def cache_key(file)
- @cache_keys ||= {}
- @cache_keys[file] ||= cache.generate_key(file, "chef-test")
+ validated_files.add(checksum(file))
end
def validate_ruby_files
@@ -118,7 +165,7 @@ class Chef
result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
false
end
-
+
def validate_ruby_file(ruby_file)
Chef::Log.debug("Testing #{ruby_file} for syntax errors...")
result = shell_out("ruby -c #{ruby_file}")
@@ -130,7 +177,7 @@ class Chef
result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
false
end
-
+
end
end
end
diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb
index 90c9ee9996..69be03731e 100644
--- a/lib/chef/cookbook_uploader.rb
+++ b/lib/chef/cookbook_uploader.rb
@@ -3,7 +3,7 @@ require 'set'
require 'rest_client'
require 'chef/exceptions'
require 'chef/knife/cookbook_metadata'
-require 'chef/checksum_cache'
+require 'chef/digester'
require 'chef/cookbook_version'
require 'chef/cookbook/syntax_check'
require 'chef/cookbook/file_system_file_vendor'
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index 0e11174a07..580a64ffbe 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -69,7 +69,7 @@ class Chef
# This is the one and only method that knows how cookbook files'
# checksums are generated.
def self.checksum_cookbook_file(filepath)
- Chef::ChecksumCache.generate_md5_checksum_for_file(filepath)
+ Chef::Digester.generate_md5_checksum_for_file(filepath)
rescue Errno::ENOENT
Chef::Log.debug("File #{filepath} does not exist, so there is no checksum to generate")
nil
diff --git a/lib/chef/digester.rb b/lib/chef/digester.rb
new file mode 100644
index 0000000000..669ff8b8a5
--- /dev/null
+++ b/lib/chef/digester.rb
@@ -0,0 +1,73 @@
+#
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Author:: Daniel DeLeo (<dan@kallistec.com>)
+# Copyright:: Copyright (c) 2009 Opscode, Inc.
+# Copyright:: Copyright (c) 2009 Daniel DeLeo
+# 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 'digest'
+
+class Chef
+ class Digester
+
+ def self.instance
+ @instance ||= new
+ end
+
+ def self.checksum_for_file(*args)
+ instance.checksum_for_file(*args)
+ end
+
+ def validate_checksum(*args)
+ self.class.validate_checksum(*args)
+ end
+
+ def checksum_for_file(file)
+ generate_checksum(file)
+ end
+
+ def generate_checksum(file)
+ checksum_file(file, Digest::SHA256.new)
+ end
+
+ def self.generate_md5_checksum_for_file(*args)
+ instance.generate_md5_checksum_for_file(*args)
+ end
+
+ def generate_md5_checksum_for_file(file)
+ checksum_file(file, Digest::MD5.new)
+ end
+
+ def generate_md5_checksum(io)
+ checksum_io(io, Digest::MD5.new)
+ end
+
+ private
+
+ def checksum_file(file, digest)
+ File.open(file, 'rb') { |f| checksum_io(f, digest) }
+ end
+
+ def checksum_io(io, digest)
+ while chunk = io.read(1024 * 8)
+ digest.update(chunk)
+ end
+ digest.hexdigest
+ end
+
+ end
+end
+
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index 0be7093e29..e818239a89 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -81,8 +81,7 @@ client_key '#{new_client_key}'
validation_client_name '#{validation_client_name}'
validation_key '#{validation_key}'
chef_server_url '#{chef_server}'
-cache_type 'BasicFile'
-cache_options( :path => '#{File.join(chef_config_path, "checksums")}' )
+syntax_check_cache_path '#{File.join(chef_config_path, "syntax_check_cache")}'
EOH
unless chef_repo.empty?
f.puts "cookbook_path [ '#{chef_repo}/cookbooks' ]"
diff --git a/lib/chef/knife/cookbook_test.rb b/lib/chef/knife/cookbook_test.rb
index dc8f12d135..b84ab9b5b4 100644
--- a/lib/chef/knife/cookbook_test.rb
+++ b/lib/chef/knife/cookbook_test.rb
@@ -25,7 +25,6 @@ class Chef
class CookbookTest < Knife
deps do
- require 'chef/checksum_cache'
require 'chef/cookbook/syntax_check'
end
diff --git a/lib/chef/mixin/checksum.rb b/lib/chef/mixin/checksum.rb
index 7b716b6285..8217296915 100644
--- a/lib/chef/mixin/checksum.rb
+++ b/lib/chef/mixin/checksum.rb
@@ -17,16 +17,16 @@
#
require 'digest/sha2'
-require 'chef/checksum_cache'
+require 'chef/digester'
class Chef
module Mixin
module Checksum
def checksum(file)
- Chef::ChecksumCache.checksum_for_file(file)
+ Chef::Digester.checksum_for_file(file)
end
-
+
end
end
end
diff --git a/lib/chef/monkey_patches/moneta.rb b/lib/chef/monkey_patches/moneta.rb
deleted file mode 100644
index 1c2895db56..0000000000
--- a/lib/chef/monkey_patches/moneta.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Author:: Seth Chisamore (<schisamo@opscode.com>)
-# Copyright:: Copyright (c) 2011 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.
-#
-
-# ensure data is written and read in binary mode
-# stops "dump format error for symbol(0x75)" errors
-module Moneta
- class BasicFile
-
- def store(key, value, options = {})
- ensure_directory_created(::File.dirname(path(key)))
- ::File.open(path(key), "wb") do |file|
- if @expires
- data = {:value => value}
- if options[:expires_in]
- data[:expires_at] = Time.now + options[:expires_in]
- end
- contents = Marshal.dump(data)
- else
- contents = Marshal.dump(value)
- end
- file.puts(contents)
- end
- end
-
- def raw_get(key)
- if ::File.respond_to?(:binread)
- data = ::File.binread(path(key))
- else
- data = ::File.open(path(key),"rb") { |f| f.read }
- end
- Marshal.load(data)
- end
-
- end
-end
diff --git a/spec/support/chef_helpers.rb b/spec/support/chef_helpers.rb
index 77cbe5b5cb..74af5f558e 100644
--- a/spec/support/chef_helpers.rb
+++ b/spec/support/chef_helpers.rb
@@ -17,8 +17,6 @@ CHEF_SPEC_DATA = File.expand_path(File.dirname(__FILE__) + "/../data/")
CHEF_SPEC_BACKUP_PATH = File.join(Dir.tmpdir, 'test-backup-path')
Chef::Config[:log_level] = :fatal
-Chef::Config[:cache_type] = "Memory"
-Chef::Config[:cache_options] = { }
Chef::Config[:persistent_queue] = false
Chef::Config[:file_backup_path] = CHEF_SPEC_BACKUP_PATH
diff --git a/spec/unit/checksum_cache_spec.rb b/spec/unit/checksum_cache_spec.rb
deleted file mode 100644
index 78e76b6dfb..0000000000
--- a/spec/unit/checksum_cache_spec.rb
+++ /dev/null
@@ -1,209 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Opscode, Inc.
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# 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::ChecksumCache do
- before(:each) do
- Chef::Config[:cache_type] = "Memory"
- Chef::Config[:cache_options] = { }
- @cache = Chef::ChecksumCache.instance
- @cache.reset!
- end
-
- describe "loading the moneta backend" do
- it "should build a Chef::ChecksumCache object" do
- @cache.should be_a_kind_of(Chef::ChecksumCache)
- end
-
- it "should set up a Moneta Cache adaptor" do
- @cache.moneta.should be_a_kind_of(Moneta::Memory)
- end
-
- it "should raise an exception if it cannot load the moneta adaptor" do
- Chef::Log.should_receive(:fatal).with(/^Could not load Moneta back end/)
- lambda {
- c = Chef::ChecksumCache.instance.reset!('WTF')
- }.should raise_error(LoadError)
- end
- end
-
- describe "when caching checksums of cookbook files and templates" do
-
- before do
- @cache.reset!("Memory", {})
- end
-
- it "proxies the class method checksum_for_file to the instance" do
- @cache.should_receive(:checksum_for_file).with("a_file_or_a_fail")
- Chef::ChecksumCache.checksum_for_file("a_file_or_a_fail")
- end
-
- it "returns a cached checksum value" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(12345))
- File.should_receive(:stat).with("riseofthemachines").and_return(fstat)
- @cache.checksum_for_file("riseofthemachines").should == "123abc"
- end
-
- it "gives nil for a cache miss" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should be_nil
- end
-
- it "treats a non-matching mtime as a cache miss" do
- @cache.moneta["chef-file-riseofthemachines"] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should be_nil
- end
-
- it "computes a checksum of a file" do
- fixture_file = CHEF_SPEC_DATA + "/checksum/random.txt"
- expected = "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
- @cache.send(:checksum_file, fixture_file, Digest::SHA256.new).should == expected
- end
-
- it "computes a checksum and stores it in the cache" do
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(555555))
- @cache.should_receive(:checksum_file).with("riseofthemachines", an_instance_of(Digest::SHA256)).and_return("ohai2uChefz")
- @cache.generate_checksum("chef-file-riseofthemachines", "riseofthemachines", fstat).should == "ohai2uChefz"
- @cache.lookup_checksum("chef-file-riseofthemachines", fstat).should == "ohai2uChefz"
- end
-
- it "returns a generated checksum if there is no cached value" do
- fixture_file = CHEF_SPEC_DATA + "/checksum/random.txt"
- expected = "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
- @cache.checksum_for_file(fixture_file).should == expected
- end
-
- it "generates a key from a file name" do
- file = "/this/is/a/test/random.rb"
- @cache.generate_key(file).should == "chef-file--this-is-a-test-random-rb"
- end
-
- it "generates a key from a file name and group" do
- file = "/this/is/a/test/random.rb"
- @cache.generate_key(file, "spec").should == "spec-file--this-is-a-test-random-rb"
- end
-
- it "returns a cached checksum value using a user defined key" do
- key = @cache.generate_key("riseofthemachines", "specs")
- @cache.moneta[key] = {"mtime" => "12345", "checksum" => "123abc"}
- fstat = mock("File.stat('riseofthemachines')", :mtime => Time.at(12345))
- File.should_receive(:stat).with("riseofthemachines").and_return(fstat)
- @cache.checksum_for_file("riseofthemachines", key).should == "123abc"
- end
-
- it "generates a checksum from a non-file IO object" do
- io = StringIO.new("riseofthemachines\nriseofthechefs\n")
- expected_md5 = '0e157ac1e2dd73191b76067fb6b4bceb'
- @cache.generate_md5_checksum(io).should == expected_md5
- end
-
- end
-
- describe "when cleaning up after outdated checksums" do
-
- before do
- Chef::ChecksumCache.reset_cache_validity
- end
-
- it "initially has no valid cached checksums" do
- Chef::ChecksumCache.valid_cached_checksums.should be_empty
- end
-
- it "adds a checksum to the list of valid cached checksums when it's created" do
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.valid_cached_checksums.should have(1).valid_checksum
- end
-
- it "adds a checksum to the list of valid cached checksums when it's read" do
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.reset_cache_validity
- @cache.checksum_for_file(File.join(CHEF_SPEC_DATA, 'checksum', 'random.txt'))
- Chef::ChecksumCache.valid_cached_checksums.should have(1).valid_checksum
- end
-
- context "with an existing set of cached checksums" do
- before do
- Chef::Config[:cache_type] = "BasicFile"
- Chef::Config[:cache_options] = {:path => File.join(CHEF_SPEC_DATA, "checksum_cache")}
-
- @expected_cached_checksums = ["chef-file--tmp-chef-rendered-template20100929-10863-600hhz-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ahd2gq-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-api8ux-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-b0r1m1-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-bfygsi-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-el14l6-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-kkbs85-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ory1ux-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-pgsq76-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ra8uim-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-t7k1g-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-t8g0sv-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-ufy6g3-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-x2d6j9-0",
- "chef-file--tmp-chef-rendered-template20100929-10863-xi0l6h-0"]
- @expected_cached_checksums.sort!
- end
-
- after do
- Chef::Config[:cache_type] = "Memory"
- Chef::Config[:cache_options] = { }
- @cache = Chef::ChecksumCache.instance
- @cache.reset!
- end
-
- it "lists all of the cached checksums in the cache directory" do
- Chef::ChecksumCache.all_cached_checksums.keys.sort.should == @expected_cached_checksums
- end
-
- it "clears all of the checksums not marked valid from the checksums directory" do
- valid_cksum_key = "chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0"
- valid_cksum_file = File.join(CHEF_SPEC_DATA, "checksum_cache", valid_cksum_key)
- @expected_cached_checksums.delete(valid_cksum_key)
-
- Chef::ChecksumCache.valid_cached_checksums << valid_cksum_key
-
- Chef::ChecksumCache.should_not_receive(:remove_unused_checksum).with(valid_cksum_file)
- @expected_cached_checksums.each do |cksum_key|
- full_path_to_cksum = File.join(CHEF_SPEC_DATA, "checksum_cache", cksum_key)
- Chef::ChecksumCache.should_receive(:remove_unused_checksum).with(full_path_to_cksum)
- end
-
- Chef::ChecksumCache.cleanup_checksum_cache
- end
-
- it "cleans all 0byte checksum files when it encounters a Marshal error" do
- @cache.moneta.stub!(:fetch).and_raise(ArgumentError)
- # This cache file is 0 bytes, raises an argument error when
- # attempting to Marshal.load
- File.should_receive(:unlink).with(File.join(CHEF_SPEC_DATA, "checksum_cache", "chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0"))
- @cache.lookup_checksum("chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0", "foo")
- end
- end
-
- end
-
-end
-
diff --git a/spec/unit/cookbook/syntax_check_spec.rb b/spec/unit/cookbook/syntax_check_spec.rb
index b41c2ddf0a..948b3c5a38 100644
--- a/spec/unit/cookbook/syntax_check_spec.rb
+++ b/spec/unit/cookbook/syntax_check_spec.rb
@@ -16,175 +16,114 @@
# limitations under the License.
#
-###################################################
-# OLD:
-###################################################
-# def test_ruby(cookbook_dir)
-# cache = Chef::ChecksumCache.instance
-# Dir[File.join(cookbook_dir, '**', '*.rb')].each do |ruby_file|
-# key = cache.generate_key(ruby_file, "chef-test")
-# fstat = File.stat(ruby_file)
-#
-# if cache.lookup_checksum(key, fstat)
-# Chef::Log.info("No change in checksum of #{ruby_file}")
-# else
-# Chef::Log.info("Testing #{ruby_file} for syntax errors...")
-# Chef::Mixin::Command.run_command(:command => "ruby -c #{ruby_file}", :output_on_failure => true)
-# cache.generate_checksum(key, ruby_file, fstat)
-# end
-# end
-# end
-#
-#def test_templates(cookbook_dir)
-# cache = Chef::ChecksumCache.instance
-# Dir[File.join(cookbook_dir, '**', '*.erb')].each do |erb_file|
-# key = cache.generate_key(erb_file, "chef-test")
-# fstat = File.stat(erb_file)
-#
-# if cache.lookup_checksum(key, fstat)
-# Chef::Log.info("No change in checksum of #{erb_file}")
-# else
-# Chef::Log.info("Testing template #{erb_file} for syntax errors...")
-# Chef::Mixin::Command.run_command(:command => "sh -c 'erubis -x #{erb_file} | ruby -c'", :output_on_failure => true)
-# cache.generate_checksum(key, erb_file, fstat)
-# end
-# end
-#end
-#
-
-###################################################
-# NEW:
-###################################################
-# def test_template_file(cookbook_dir, erb_file)
-# Chef::Log.debug("Testing template #{erb_file} for syntax errors...")
-# result = shell_out("sh -c 'erubis -x #{erb_file} | ruby -c'")
-# result.error!
-# rescue Mixlib::ShellOut::ShellCommandFailed
-# file_relative_path = erb_file[/^#{Regexp.escape(cookbook_dir+File::Separator)}(.*)/, 1]
-# Chef::Log.fatal("Erb template #{file_relative_path} has a syntax error:")
-# result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
-# exit(1)
-# end
-#
-# def test_ruby_file(cookbook_dir, ruby_file)
-# Chef::Log.debug("Testing #{ruby_file} for syntax errors...")
-# result = shell_out("ruby -c #{ruby_file}")
-# result.error!
-# rescue Mixlib::ShellOut::ShellCommandFailed
-# file_relative_path = ruby_file[/^#{Regexp.escape(cookbook_dir+File::Separator)}(.*)/, 1]
-# Chef::Log.fatal("Cookbook file #{file_relative_path} has a syntax error:")
-# result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
-# exit(1)
-# end
-#
-
require 'spec_helper'
require "chef/cookbook/syntax_check"
describe Chef::Cookbook::SyntaxCheck do
+
+ let(:cookbook_path) { File.join(CHEF_SPEC_DATA, 'cookbooks', 'openldap') }
+ let(:syntax_check) { Chef::Cookbook::SyntaxCheck.new(cookbook_path) }
+
before do
Chef::Log.logger = Logger.new(StringIO.new)
+ Chef::Log.level = :warn # suppress "Syntax OK" messages
- @cookbook_path = File.join(CHEF_SPEC_DATA, 'cookbooks', 'openldap')
- @attr_files = %w{default.rb smokey.rb}.map { |f| File.join(@cookbook_path, 'attributes', f) }
- @defn_files = %w{client.rb server.rb}.map { |f| File.join(@cookbook_path, 'definitions', f)}
- @recipes = %w{default.rb gigantor.rb one.rb}.map { |f| File.join(@cookbook_path, 'recipes', f) }
+ @attr_files = %w{default.rb smokey.rb}.map { |f| File.join(cookbook_path, 'attributes', f) }
+ @defn_files = %w{client.rb server.rb}.map { |f| File.join(cookbook_path, 'definitions', f)}
+ @recipes = %w{default.rb gigantor.rb one.rb}.map { |f| File.join(cookbook_path, 'recipes', f) }
@ruby_files = @attr_files + @defn_files + @recipes
- @template_files = %w{openldap_stuff.conf.erb openldap_variable_stuff.conf.erb test.erb}.map { |f| File.join(@cookbook_path, 'templates', 'default', f)}
+ @template_files = %w{openldap_stuff.conf.erb openldap_variable_stuff.conf.erb test.erb}.map { |f| File.join(cookbook_path, 'templates', 'default', f)}
- @syntax_check = Chef::Cookbook::SyntaxCheck.new(@cookbook_path)
end
it "creates a syntax checker given the cookbook name when Chef::Config.cookbook_path is set" do
- Chef::Config[:cookbook_path] = File.dirname(@cookbook_path)
+ Chef::Config[:cookbook_path] = File.dirname(cookbook_path)
syntax_check = Chef::Cookbook::SyntaxCheck.for_cookbook(:openldap)
- syntax_check.cookbook_path.should == @cookbook_path
+ syntax_check.cookbook_path.should == cookbook_path
end
describe "when first created" do
it "has the path to the cookbook to syntax check" do
- @syntax_check.cookbook_path.should == @cookbook_path
- end
-
- it "has access to the checksum cache" do
- @syntax_check.cache.should equal(Chef::ChecksumCache.instance)
+ syntax_check.cookbook_path.should == cookbook_path
end
it "lists the ruby files in the cookbook" do
- @syntax_check.ruby_files.sort.should == @ruby_files.sort
+ syntax_check.ruby_files.sort.should == @ruby_files.sort
end
it "lists the erb templates in the cookbook" do
- @syntax_check.template_files.sort.should == @template_files.sort
+ syntax_check.template_files.sort.should == @template_files.sort
end
end
describe "when validating cookbooks" do
+ let(:cache_path) { Dir.mktmpdir }
+
before do
- Chef::Config[:cache_type] = 'Memory'
- @checksum_cache_klass = Class.new(Chef::ChecksumCache)
- @checksum_cache = @checksum_cache_klass.instance
- @checksum_cache.reset!('Memory')
- @syntax_check.stub!(:cache).and_return(@checksum_cache)
- $stdout.stub!(:write)
+ Chef::Config[:syntax_check_cache_path] = cache_path
+ end
+
+ after do
+ FileUtils.rm_rf(cache_path) if File.exist?(cache_path)
+ Chef::Config[:syntax_check_cache_path] = nil
end
describe "and the files have not been syntax checked previously" do
it "shows that all ruby files require a syntax check" do
- @syntax_check.untested_ruby_files.sort.should == @ruby_files.sort
+ syntax_check.untested_ruby_files.sort.should == @ruby_files.sort
end
it "shows that all template files require a syntax check" do
- @syntax_check.untested_template_files.sort.should == @template_files.sort
+ syntax_check.untested_template_files.sort.should == @template_files.sort
end
it "removes a ruby file from the list of untested files after it is marked as validated" do
- recipe = File.join(@cookbook_path, 'recipes', 'default.rb')
- @syntax_check.validated(recipe)
- @syntax_check.untested_ruby_files.should_not include(recipe)
+ recipe = File.join(cookbook_path, 'recipes', 'default.rb')
+ syntax_check.validated(recipe)
+ syntax_check.untested_ruby_files.should_not include(recipe)
end
it "removes a template file from the list of untested files after it is marked as validated" do
- template = File.join(@cookbook_path, 'templates', 'default', 'test.erb')
- @syntax_check.validated(template)
- @syntax_check.untested_template_files.should_not include(template)
+ template = File.join(cookbook_path, 'templates', 'default', 'test.erb')
+ syntax_check.validated(template)
+ syntax_check.untested_template_files.should_not include(template)
end
it "validates all ruby files" do
- @syntax_check.validate_ruby_files.should be_true
- @syntax_check.untested_ruby_files.should be_empty
+ syntax_check.validate_ruby_files.should be_true
+ syntax_check.untested_ruby_files.should be_empty
end
it "validates all templates" do
- @syntax_check.validate_templates.should be_true
- @syntax_check.untested_template_files.should be_empty
+ syntax_check.validate_templates.should be_true
+ syntax_check.untested_template_files.should be_empty
end
describe "and a file has a syntax error" do
before do
- @cookbook_path = File.join(CHEF_SPEC_DATA, 'cookbooks', 'borken')
- @syntax_check.cookbook_path.replace(@cookbook_path)
+ cookbook_path = File.join(CHEF_SPEC_DATA, 'cookbooks', 'borken')
+ syntax_check.cookbook_path.replace(cookbook_path)
end
it "it indicates that a ruby file has a syntax error" do
- @syntax_check.validate_ruby_files.should be_false
+ syntax_check.validate_ruby_files.should be_false
end
it "does not remove the invalid file from the list of untested files" do
- @syntax_check.untested_ruby_files.should include(File.join(@cookbook_path, 'recipes', 'default.rb'))
- lambda { @syntax_check.validate_ruby_files }.should_not change(@syntax_check, :untested_ruby_files)
+ syntax_check.untested_ruby_files.should include(File.join(cookbook_path, 'recipes', 'default.rb'))
+ lambda { syntax_check.validate_ruby_files }.should_not change(syntax_check, :untested_ruby_files)
end
it "indicates that a template file has a syntax error" do
- @syntax_check.validate_templates.should be_false
+ syntax_check.validate_templates.should be_false
end
it "does not remove the invalid template from the list of untested templates" do
- @syntax_check.untested_template_files.should include(File.join(@cookbook_path, 'templates', 'default', 'borken.erb'))
- lambda {@syntax_check.validate_templates}.should_not change(@syntax_check, :untested_template_files)
+ syntax_check.untested_template_files.should include(File.join(cookbook_path, 'templates', 'default', 'borken.erb'))
+ lambda {syntax_check.validate_templates}.should_not change(syntax_check, :untested_template_files)
end
end
@@ -193,18 +132,18 @@ describe Chef::Cookbook::SyntaxCheck do
describe "and the files have been syntax checked previously" do
before do
- @syntax_check.untested_ruby_files.each { |f| @syntax_check.validated(f) }
- @syntax_check.untested_template_files.each { |f| @syntax_check.validated(f) }
+ syntax_check.untested_ruby_files.each { |f| syntax_check.validated(f) }
+ syntax_check.untested_template_files.each { |f| syntax_check.validated(f) }
end
it "does not syntax check ruby files" do
- @syntax_check.should_not_receive(:shell_out)
- @syntax_check.validate_ruby_files.should be_true
+ syntax_check.should_not_receive(:shell_out)
+ syntax_check.validate_ruby_files.should be_true
end
it "does not syntax check templates" do
- @syntax_check.should_not_receive(:shell_out)
- @syntax_check.validate_templates.should be_true
+ syntax_check.should_not_receive(:shell_out)
+ syntax_check.validate_templates.should be_true
end
end
end
diff --git a/spec/unit/digester_spec.rb b/spec/unit/digester_spec.rb
new file mode 100644
index 0000000000..28e3e918fe
--- /dev/null
+++ b/spec/unit/digester_spec.rb
@@ -0,0 +1,50 @@
+#
+# Author:: Adam Jacob (<adam@opscode.com>)
+# Author:: Daniel DeLeo (<dan@kallistec.com>)
+# Copyright:: Copyright (c) 2009 Opscode, Inc.
+# Copyright:: Copyright (c) 2009 Daniel DeLeo
+# 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::Digester do
+ before(:each) do
+ @cache = Chef::Digester.instance
+ end
+
+ describe "when computing checksums of cookbook files and templates" do
+
+ it "proxies the class method checksum_for_file to the instance" do
+ @cache.should_receive(:checksum_for_file).with("a_file_or_a_fail")
+ Chef::Digester.checksum_for_file("a_file_or_a_fail")
+ end
+
+ it "computes a checksum of a file" do
+ fixture_file = CHEF_SPEC_DATA + "/checksum/random.txt"
+ expected = "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
+ @cache.checksum_for_file(fixture_file).should == expected
+ end
+
+ it "generates a checksum from a non-file IO object" do
+ io = StringIO.new("riseofthemachines\nriseofthechefs\n")
+ expected_md5 = '0e157ac1e2dd73191b76067fb6b4bceb'
+ @cache.generate_md5_checksum(io).should == expected_md5
+ end
+
+ end
+
+end
+
diff --git a/spec/unit/mixin/checksum_spec.rb b/spec/unit/mixin/checksum_spec.rb
index dec270e18f..19af1c7d2b 100644
--- a/spec/unit/mixin/checksum_spec.rb
+++ b/spec/unit/mixin/checksum_spec.rb
@@ -27,12 +27,12 @@ end
describe Chef::Mixin::Checksum do
before(:each) do
@checksum_user = Chef::CMCCheck.new
- @cache = Chef::ChecksumCache.instance
+ @cache = Chef::Digester.instance
@file = CHEF_SPEC_DATA + "/checksum/random.txt"
@stat = mock("File::Stat", { :mtime => Time.at(0) })
File.stub!(:stat).and_return(@stat)
end
-
+
it "gets the checksum of a file" do
@checksum_user.checksum(@file).should == "09ee9c8cc70501763563bcf9c218d71b2fbf4186bf8e1e0da07f0f42c80a3394"
end
diff --git a/spec/unit/provider/file_spec.rb b/spec/unit/provider/file_spec.rb
index 23352a5124..8c575e815e 100644
--- a/spec/unit/provider/file_spec.rb
+++ b/spec/unit/provider/file_spec.rb
@@ -56,68 +56,68 @@ describe Chef::Provider::File do
context "load_current_resource_attrs", :unix_only do
it "should collect the current state of the file on the filesystem and populate current_resource" do
# test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
- # test execution
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
+
+ # test execution
@provider.load_current_resource
-
+
# post-condition checks
@provider.current_resource.mode.should == 0600
@provider.current_resource.owner.should == 0
@provider.current_resource.group.should == 0
end
-
+
it "should NOT update the new_resource state with the current_resourse state if new_resource state is already specified" do
# test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
+
@provider.new_resource.group(1)
@provider.new_resource.owner(1)
@provider.new_resource.mode(0644)
-
- # test execution
+
+ # test execution
@provider.load_current_resource
-
+
# post-condition checks
@provider.new_resource.group.should == 1
@provider.new_resource.owner.should == 1
@provider.new_resource.mode.should == 0644
end
-
+
it "should update the new_resource state with the current_resource state if the new_resource state is not specified." do
# test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(2).times.with(@resource.path).and_return(stat_struct)
+
@provider.new_resource.group(nil)
@provider.new_resource.owner(nil)
@provider.new_resource.mode(nil)
-
- # test execution
+
+ # test execution
@provider.load_current_resource
-
+
# post-condition checks
@provider.new_resource.group.should eql(@provider.current_resource.group)
@provider.new_resource.owner.should eql(@provider.current_resource.owner)
@provider.new_resource.mode.should eql(@provider.current_resource.mode)
end
-
+
it "should update the new_resource when attempting to set the new state" do
# test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
# called once in update_new_file_state and once in checksum
- ::File.should_receive(:stat).twice.with(@provider.new_resource.path).and_return(stat_struct)
+ ::File.should_receive(:stat).with(@provider.new_resource.path).and_return(stat_struct)
::File.should_receive(:directory?).once.with(@provider.new_resource.path).and_return(false)
-
+
@provider.new_resource.group(nil)
@provider.new_resource.owner(nil)
@provider.new_resource.mode(nil)
-
- # test exectution
+
+ # test exectution
@provider.update_new_file_state
-
+
# post-condition checks
@provider.new_resource.group.should == 0
@provider.new_resource.owner.should == 0
@@ -174,6 +174,8 @@ describe Chef::Provider::File do
@provider.new_resource.content "foobar"
@provider.should_receive(:diff_current_from_content).and_return("")
@provider.should_receive(:backup)
+ # checksum check
+ File.should_receive(:open).with(@provider.new_resource.path, "rb").and_yield(io)
File.should_receive(:open).with(@provider.new_resource.path, "w").and_yield(io)
@provider.set_content
io.string.should == "foobar"
@@ -182,7 +184,8 @@ describe Chef::Provider::File do
it "should not set the content of the file if it already matches the requested content" do
@provider.load_current_resource
@provider.new_resource.content IO.read(@resource.path)
- File.stub!(:open).and_return(1)
+ # Checksum check:
+ File.should_receive(:open).with(@resource.path, "rb").and_yield(StringIO.new(@resource.content))
File.should_not_receive(:open).with(@provider.new_resource.path, "w")
lambda { @provider.set_content }.should_not raise_error
@resource.should_not be_updated_by_last_action
@@ -487,7 +490,7 @@ describe Chef::Provider::File do
it "should return valid diff output when content does not match the string content provided" do
Tempfile.open("some-temp") do |file|
@resource.path file.path
- @provider = Chef::Provider::File.new(@resource, @run_context)
+ @provider = Chef::Provider::File.new(@resource, @run_context)
@provider.load_current_resource
result = @provider.diff_current_from_content "foo baz"
# remove the file name info which varies.
diff --git a/spec/unit/provider/template_spec.rb b/spec/unit/provider/template_spec.rb
index 6747876d61..f5d30f0219 100644
--- a/spec/unit/provider/template_spec.rb
+++ b/spec/unit/provider/template_spec.rb
@@ -156,7 +156,6 @@ describe Chef::Provider::Template do
describe "when the target has the correct content" do
before do
- Chef::ChecksumCache.instance.reset!
File.open(@rendered_file_location, "w") { |f| f.print "slappiness is a warm gun" }
@current_resource.checksum('4ff94a87794ed9aefe88e734df5a66fc8727a179e9496cbd88e3b5ec762a5ee9')
@access_controls = mock("access controls")