Permalink
Browse files

Add Chef resources and assertions.

  • Loading branch information...
1 parent f266c27 commit 52d61d1c49e88e4227f639ed5a0af255550e20eb Andrew Crump committed Apr 20, 2012
View
@@ -1,5 +1,6 @@
#!/usr/bin/env rake
require "bundler/gem_tasks"
+require "rake/testtask"
desc 'Verify that nothing is broken against the simple solo example'
task :test do
@@ -8,4 +9,9 @@ task :test do
end
end
-task :default => :test
+Rake::TestTask.new do |t|
+ t.name = 'spec'
+ t.pattern = 'spec/**/*_spec.rb'
+end
+
+task :default => [:spec, :test]
@@ -1,8 +1,12 @@
require 'minitest-chef-handler/context'
+require 'minitest-chef-handler/resources'
require 'minitest-chef-handler/unit'
require 'minitest-chef-handler/spec'
require 'minitest-chef-handler/runner'
+require 'minitest-chef-handler/assertions'
+require 'minitest-chef-handler/infections'
+
module MiniTest
module Chef
class Handler < ::Chef::Handler
@@ -0,0 +1,129 @@
+module MiniTest
+ module Chef
+ module Assertions
+
+ def self.resource_exists(name, options)
+ options[:description] = name unless options[:description]
+ define_method("assert_#{name}_exists") do |resource|
+ refute resource.send(options[:field]).nil?,
+ "Expected #{options[:description]} '#{resource.name}' to exist"
+ resource
+ end
+ define_method("refute_#{name}_exists") do |resource|
+ assert resource.send(options[:field]).nil?,
+ "Expected #{options[:description]} '#{resource.name}' to not exist"
+ resource
+ end
+ end
+
+ resource_exists :cron, :field => :command, :description => 'cron entry'
+ resource_exists :group, :field => :gid
+ resource_exists :ifconfig, :field => :device, :description => 'network interface'
+ resource_exists :link, :field => :to
+ resource_exists :user, :field => :uid
+
+ def assert_enabled(service)
+ assert service.enabled, "Expected service '#{service.name}' to be enabled"
+ service
+ end
+
+ def refute_enabled(service)
+ refute service.enabled, "Expected service '#{service.name}' to not be enabled"
+ service
+ end
+
+ def assert_group_includes(members, group)
+ members = [members] unless members.respond_to?(:&)
+ assert group.members & members == members, "Expected group '#{group.name}' to include members: #{members.join(', ')}"
+ group
+ end
+
+ def refute_group_includes(members, group)
+ members = [members] unless members.respond_to?(:&)
+ refute group.members & members == members, "Expected group '#{group.name}' not to include members: #{members.join(', ')}"
+ group
+ end
+
+ def assert_includes_content(file, content)
+ assert File.read(file.path).include?(content), "Expected file '#{file.path}' to include the specified content"
+ file
+ end
+
+ def refute_includes_content(file, content)
+ refute File.read(file.path).include?(content), "Expected file '#{file.path}' not to include the specified content"
+ file
+ end
+
+ def assert_installed(package)
+ refute package.version.nil?, "Expected package '#{package.name}' to be installed"
+ package
+ end
+
+ def refute_installed(package)
+ assert package.version.nil?, "Expected package '#{package.name}' to not be installed"
+ package
+ end
+
+ def assert_matches_content(file, regexp)
+ assert File.read(file.path).match(regexp), "Expected the contents of file '#{file.path}' to match the regular expression '#{regexp}'"
+ file
+ end
+
+ def refute_matches_content(file, regexp)
+ refute File.read(file.path).match(regexp), "Expected the contents of file '#{file.path}' not to match the regular expression '#{regexp}'"
+ file
+ end
+
+ def assert_modified_after(file_or_dir, time)
+ assert File.mtime(file_or_dir.path).to_i >= time.to_i, "Expected the file '#{file_or_dir.path}' to have been modified after '#{time}'"
+ file_or_dir
+ end
+
+ def refute_modified_after(file_or_dir, time)
+ refute File.mtime(file_or_dir.path) >= time, "Expected the file '#{file_or_dir.path}' not to have been modified after '#{time}'"
+ file_or_dir
+ end
+
+ def assert_mounted(mount)
+ assert mount.mounted, "Expected mount point '#{mount.name}' to be mounted"
+ mount
+ end
+
+ def refute_mounted(mount)
+ refute mount.mounted, "Expected mount point '#{mount.name}' to not be mounted"
+ mount
+ end
+
+ def assert_mount_enabled(mount)
+ assert mount.enabled, "Expected mount point '#{mount.name}' to be enabled"
+ mount
+ end
+
+ def refute_mount_enabled(mount)
+ refute mount.enabled, "Expected mount point '#{mount.name}' to not be enabled"
+ mount
+ end
+
+ def assert_path_exists(file_or_dir)
+ assert File.exists?(file_or_dir.path), "Expected path '#{file_or_dir.path}' to exist"
+ file_or_dir
+ end
+
+ def refute_path_exists(file_or_dir)
+ refute File.exists?(file_or_dir.path), "Expected path '#{file_or_dir.path}' not to exist"
+ file_or_dir
+ end
+
+ def assert_running(service)
+ assert service.running, "Expected service '#{service.name}' to be running"
+ service
+ end
+
+ def refute_running(service)
+ refute service.running, "Expected service '#{service.name}' not to be running"
+ service
+ end
+
+ end
+ end
+end
@@ -0,0 +1,37 @@
+require 'chef'
+
+module MiniTest
+ module Chef
+ module Infections extend ::Chef::Mixin::ConvertToClassName
+
+ def self.infect_resource(resource, meth, new_name)
+ clazz = ::Chef::Resource.const_get(convert_to_class_name(resource.to_s))
+ clazz.infect_an_assertion "assert_#{meth}".to_sym,
+ "must_#{new_name}".to_sym, :only_one_argument
+ clazz.infect_an_assertion "refute_#{meth}".to_sym,
+ "wont_#{new_name}".to_sym, :only_one_argument
+ end
+
+ infect_resource :cron, :cron_exists, :exist
+ infect_resource :directory, :modified_after, :be_modified_after
+ infect_resource :directory, :path_exists, :exist
+ infect_resource :file, :includes_content, :include
+ infect_resource :file, :matches_content, :match
+ infect_resource :file, :modified_after, :be_modified_after
+ infect_resource :file, :path_exists, :exist
+ infect_resource :group, :group_exists, :exist
+ infect_resource :ifconfig, :ifconfig_exists, :exist
+ infect_resource :link, :link_exists, :exist
+ infect_resource :mount, :mounted, :be_mounted
+ infect_resource :mount, :mount_enabled, :be_enabled
+ infect_resource :service, :enabled, :be_enabled
+ infect_resource :service, :running, :be_running
+ infect_resource :package, :installed, :be_installed
+ infect_resource :user, :user_exists, :exist
+
+ ::Chef::Resource::Group.infect_an_assertion :assert_group_includes, :must_include
+ ::Chef::Resource::Group.infect_an_assertion :refute_group_includes, :wont_include
+
+ end
+ end
+end
@@ -0,0 +1,54 @@
+require 'chef'
+require 'etc'
+require 'minitest/unit'
+
+module MiniTest
+ module Chef
+ module Resources
+ include ::Chef::Mixin::ConvertToClassName
+
+ def self.register_resource(resource, *required_args)
+ define_method(resource) do |name, *options|
+ clazz = ::Chef::Resource.const_get(convert_to_class_name(resource.to_s))
+ res = clazz.new(name, run_context)
+ required_args.each do |arg|
+ res.send(arg, options.first[arg])
+ end
+ provider = ::Chef::Platform.provider_for_resource(res)
+ provider.load_current_resource
+ provider.current_resource
+ end
+ end
+
+ [:cron, :directory, :file, :group,
+ :link, :package, :service, :user].each{ |r| register_resource(r) }
+
+ register_resource(:ifconfig, :device)
+ register_resource(:mount, :device)
+
+ ::Chef::Resource.class_eval do
+ include MiniTest::Assertions
+ def with(attribute, values)
+ actual_values = resource_value(attribute, values)
+ assert_equal values, actual_values,
+ "The #{resource_name} does not have the expected #{attribute}"
+ self
+ end
+ alias :and :with
+ alias :must_have :with
+ private
+
+ def resource_value(attribute, values)
+ case attribute
+ when :mode then mode.kind_of?(Integer) ? mode.to_s(8) : mode.to_s
+ when :owner || :user then Etc.getpwuid(owner).name
+ when :group then Etc.getgrgid(group).name
+ else send(attribute)
+ end
+ end
+
+ end
+
+ end
+ end
+end
@@ -3,7 +3,9 @@ module Chef
require 'minitest/spec'
class Spec < MiniTest::Spec
+ include Assertions
include Context
+ include Resources
end
MiniTest::Spec.register_spec_type(/\Arecipe::/, MiniTest::Chef::Spec)
@@ -3,7 +3,9 @@ module Chef
require 'minitest/unit'
class TestCase < MiniTest::Unit::TestCase
+ include Assertions
include Context
+ include Resources
end
end
end
Oops, something went wrong.

0 comments on commit 52d61d1

Please sign in to comment.