From 68fdb6ba4de74a26774cdfbf7c1eb4c5808b0245 Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Tue, 29 Jan 2013 23:03:27 +0100 Subject: [PATCH 1/6] Add tests to assert number of classes and resources --- spec/classes/sysctl_common_spec.rb | 4 ++++ spec/defines/sysctl_spec.rb | 1 + 2 files changed, 5 insertions(+) diff --git a/spec/classes/sysctl_common_spec.rb b/spec/classes/sysctl_common_spec.rb index 88bfaf85..b51c58d8 100644 --- a/spec/classes/sysctl_common_spec.rb +++ b/spec/classes/sysctl_common_spec.rb @@ -37,4 +37,8 @@ it { should create_class("sysctl::common")\ .with_test_param("yes") } + it { should have_class_count(1) } + it { should have_exec_resource_count(1) } + # one exec resource and one notify resource from the default node (site.pp) + it { should have_resource_count(2) } end diff --git a/spec/defines/sysctl_spec.rb b/spec/defines/sysctl_spec.rb index 47a6a4c9..9aa8dadb 100644 --- a/spec/defines/sysctl_spec.rb +++ b/spec/defines/sysctl_spec.rb @@ -11,4 +11,5 @@ .with_onlyif("match vm.swappiness[.='60'] size == 0") \ .with_notify('Exec[sysctl/reload]')\ .without_foo } + it { should have_sysctl_resource_count(1) } end From 4110bfd527383f35410b47e2de6d521e3c6c717b Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Tue, 29 Jan 2013 23:34:09 +0100 Subject: [PATCH 2/6] Generic class for counting resources and classes --- lib/rspec-puppet/matchers/count_generic.rb | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 lib/rspec-puppet/matchers/count_generic.rb diff --git a/lib/rspec-puppet/matchers/count_generic.rb b/lib/rspec-puppet/matchers/count_generic.rb new file mode 100644 index 00000000..fc432aff --- /dev/null +++ b/lib/rspec-puppet/matchers/count_generic.rb @@ -0,0 +1,86 @@ +module RSpec::Puppet + module ManifestMatchers + class CountGeneric + def initialize(type, count, *method) + if type.nil? + @type = method.to_s.gsub(/^have_(.+)_resource_count$/, '\1') + else + @type = type + end + @referenced_type = referenced_type(@type) + @expected_number = count.to_i + end + + def matches?(catalogue) + ret = true + + case @type + when "class" + actual = catalogue.resources.select do |res| + res.type.eql? "Class" + end + + # Puppet automatically adds Class[main] and Class[Settings] + @actual_number = actual.length - 2 + when "resource" + actual = catalogue.resources.select do |res| + !res.type.eql? "Class" and !res.type.eql? "Node" + end + + # Puppet automatically adds Stage[main] + @actual_number = actual.length - 1 + else + actual = catalogue.resources.select do |res| + res.type.eql? "#{@referenced_type}" + end + + @actual_number = actual.length + end + + unless @actual_number == @expected_number + ret = false + end + + ret + end + + def description + desc = [] + + desc << "contain exactly #{@expected_number}" + if @type == "class" + desc << "#{@expected_number == 1 ? "class" : "classes" }" + else + unless @type == "resource" + desc << "#{@referenced_type}" + end + desc << "#{@expected_number == 1 ? "resource" : "resources" }" + end + + desc.join(" ") + end + + def failure_message_for_should + "expected that the catalogue would " + description + " but it contains #{@actual_number}" + end + + def failure_message_for_should_not + "expected that the catalogue would not " + description + " but it does" + end + + private + + def referenced_type(type) + type.split('__').map { |r| r.capitalize }.join('::') + end + end + + def have_class_count(count) + RSpec::Puppet::ManifestMatchers::CountGeneric.new('class', count) + end + + def have_resource_count(count) + RSpec::Puppet::ManifestMatchers::CountGeneric.new('resource', count) + end + end +end From fda613f1f9b1f7787c96ddc4264ea70b316b2f3c Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Tue, 29 Jan 2013 23:40:16 +0100 Subject: [PATCH 3/6] Factor out dynamic matchers and include count matchers --- lib/rspec-puppet/matchers.rb | 2 ++ lib/rspec-puppet/matchers/create_generic.rb | 5 ----- lib/rspec-puppet/matchers/dynamic_matchers.rb | 9 +++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 lib/rspec-puppet/matchers/dynamic_matchers.rb diff --git a/lib/rspec-puppet/matchers.rb b/lib/rspec-puppet/matchers.rb index d92a0f70..f1853a67 100644 --- a/lib/rspec-puppet/matchers.rb +++ b/lib/rspec-puppet/matchers.rb @@ -2,3 +2,5 @@ require 'rspec-puppet/matchers/create_resource' require 'rspec-puppet/matchers/include_class' require 'rspec-puppet/matchers/run' +require 'rspec-puppet/matchers/count_generic' +require 'rspec-puppet/matchers/dynamic_matchers' diff --git a/lib/rspec-puppet/matchers/create_generic.rb b/lib/rspec-puppet/matchers/create_generic.rb index 593c1f95..2e5c5cee 100644 --- a/lib/rspec-puppet/matchers/create_generic.rb +++ b/lib/rspec-puppet/matchers/create_generic.rb @@ -124,10 +124,5 @@ def errors @errors.nil? ? "" : " with #{@errors.join(', and parameter ')}" end end - - def method_missing(method, *args, &block) - return RSpec::Puppet::ManifestMatchers::CreateGeneric.new(method, *args, &block) if method.to_s =~ /^(create|contain)_/ - super - end end end diff --git a/lib/rspec-puppet/matchers/dynamic_matchers.rb b/lib/rspec-puppet/matchers/dynamic_matchers.rb new file mode 100644 index 00000000..d0616b9a --- /dev/null +++ b/lib/rspec-puppet/matchers/dynamic_matchers.rb @@ -0,0 +1,9 @@ +module RSpec::Puppet + module ManifestMatchers + def method_missing(method, *args, &block) + return RSpec::Puppet::ManifestMatchers::CreateGeneric.new(method, *args, &block) if method.to_s =~ /^(create|contain)_/ + return RSpec::Puppet::ManifestMatchers::CountGeneric.new(nil, args[0], method) if method.to_s =~ /^have_.+_count$/ + super + end + end +end From 32f9c4779b66c909929f3cd786cb46713f65826a Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Tue, 29 Jan 2013 23:44:43 +0100 Subject: [PATCH 4/6] Update gemspec --- rspec-puppet.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rspec-puppet.gemspec b/rspec-puppet.gemspec index aae0b789..737d949d 100644 --- a/rspec-puppet.gemspec +++ b/rspec-puppet.gemspec @@ -18,6 +18,8 @@ Gem::Specification.new do |s| 'lib/rspec-puppet/matchers/create_resource.rb', 'lib/rspec-puppet/matchers/include_class.rb', 'lib/rspec-puppet/matchers/run.rb', + 'lib/rspec-puppet/matchers/count_generic.rb', + 'lib/rspec-puppet/matchers/dynamic_matchers.rb', 'lib/rspec-puppet/matchers.rb', 'lib/rspec-puppet/setup.rb', 'lib/rspec-puppet/support.rb', From 5f6e1406ce050094c132a4ac5a8da4e1da063fce Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Wed, 30 Jan 2013 00:08:11 +0100 Subject: [PATCH 5/6] Update README with new matchers --- README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/README.md b/README.md index 7c64d61c..b3d27fc6 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,41 @@ it { should contain_service('keystone').without( )} ``` +#### Checking the number of resources + +You can test the number of resources in the catalogue with the +`have_resource_count` matcher. + +```ruby +it { should have_resource_count(2) } +``` + +The number of classes in the catalogue can be checked with the +`have_class_count` matcher. + +```ruby +it { should have_class_count(2) } +``` + +You can also test the number of a specific resource type, by using the generic +`have__count` matcher. + +```ruby +it { should have_exec_resource_count(1) } +``` + +This last matcher also works for defined types. If the resource type contains +::, you can replace it with __ (two underscores). + +```ruby +it { should have_logrotate__rule_count(3) } +``` + +*NOTE*: when testing a class, the catalogue generated will always contain at +least one class, the class under test. The same holds for defined types, the +catalogue generated when testing a defined type will have at least one resource +(the defined type itself). + ### Writing tests #### Basic test structure From dd6476162adb27bd73533e8a289843313fe3c2d1 Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Wed, 30 Jan 2013 22:34:14 +0100 Subject: [PATCH 6/6] Different handling of .to_s method in ruby 1.9 for one-element array --- lib/rspec-puppet/matchers/count_generic.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rspec-puppet/matchers/count_generic.rb b/lib/rspec-puppet/matchers/count_generic.rb index fc432aff..ef9f7d6f 100644 --- a/lib/rspec-puppet/matchers/count_generic.rb +++ b/lib/rspec-puppet/matchers/count_generic.rb @@ -3,7 +3,7 @@ module ManifestMatchers class CountGeneric def initialize(type, count, *method) if type.nil? - @type = method.to_s.gsub(/^have_(.+)_resource_count$/, '\1') + @type = method[0].to_s.gsub(/^have_(.+)_resource_count$/, '\1') else @type = type end