diff options
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/puppet_spec/compiler.rb | 46 | ||||
-rw-r--r-- | spec/lib/puppet_spec/database.rb | 29 | ||||
-rwxr-xr-x | spec/lib/puppet_spec/files.rb | 60 | ||||
-rwxr-xr-x | spec/lib/puppet_spec/fixtures.rb | 28 | ||||
-rw-r--r-- | spec/lib/puppet_spec/matchers.rb | 120 | ||||
-rw-r--r-- | spec/lib/puppet_spec/modules.rb | 26 | ||||
-rw-r--r-- | spec/lib/puppet_spec/pops.rb | 16 | ||||
-rw-r--r-- | spec/lib/puppet_spec/scope.rb | 14 | ||||
-rw-r--r-- | spec/lib/puppet_spec/settings.rb | 15 | ||||
-rwxr-xr-x | spec/lib/puppet_spec/verbose.rb | 9 |
10 files changed, 363 insertions, 0 deletions
diff --git a/spec/lib/puppet_spec/compiler.rb b/spec/lib/puppet_spec/compiler.rb new file mode 100644 index 0000000..22e923d --- /dev/null +++ b/spec/lib/puppet_spec/compiler.rb @@ -0,0 +1,46 @@ +module PuppetSpec::Compiler + def compile_to_catalog(string, node = Puppet::Node.new('foonode')) + Puppet[:code] = string + Puppet::Parser::Compiler.compile(node) + end + + def compile_to_ral(manifest) + catalog = compile_to_catalog(manifest) + ral = catalog.to_ral + ral.finalize + ral + end + + def compile_to_relationship_graph(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) + ral = compile_to_ral(manifest) + graph = Puppet::Graph::RelationshipGraph.new(prioritizer) + graph.populate_from(ral) + graph + end + + if Puppet.version.to_f >= 3.3 + def apply_compiled_manifest(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) + transaction = Puppet::Transaction.new(compile_to_ral(manifest), + Puppet::Transaction::Report.new("apply"), + prioritizer) + transaction.evaluate + transaction.report.finalize_report + + transaction + end + else + def apply_compiled_manifest(manifest) + transaction = Puppet::Transaction.new(compile_to_ral(manifest), Puppet::Transaction::Report.new("apply")) + transaction.evaluate + transaction.report.finalize_report + + transaction + end + end + + def order_resources_traversed_in(relationships) + order_seen = [] + relationships.traverse { |resource| order_seen << resource.ref } + order_seen + end +end diff --git a/spec/lib/puppet_spec/database.rb b/spec/lib/puppet_spec/database.rb new file mode 100644 index 0000000..069ca15 --- /dev/null +++ b/spec/lib/puppet_spec/database.rb @@ -0,0 +1,29 @@ +# This just makes some nice things available at global scope, and for setup of +# tests to use a real fake database, rather than a fake stubs-that-don't-work +# version of the same. Fun times. +def sqlite? + if $sqlite.nil? + begin + require 'sqlite3' + $sqlite = true + rescue LoadError + $sqlite = false + end + end + $sqlite +end + +def can_use_scratch_database? + sqlite? and Puppet.features.rails? +end + + +# This is expected to be called in your `before :each` block, and will get you +# ready to roll with a serious database and all. Cleanup is handled +# automatically for you. Nothing to do there. +def setup_scratch_database + Puppet[:dbadapter] = 'sqlite3' + Puppet[:dblocation] = ':memory:' + Puppet[:railslog] = PuppetSpec::Files.tmpfile('storeconfigs.log') + Puppet::Rails.init +end diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb new file mode 100755 index 0000000..65b04aa --- /dev/null +++ b/spec/lib/puppet_spec/files.rb @@ -0,0 +1,60 @@ +require 'fileutils' +require 'tempfile' +require 'tmpdir' +require 'pathname' + +# A support module for testing files. +module PuppetSpec::Files + def self.cleanup + $global_tempfiles ||= [] + while path = $global_tempfiles.pop do + begin + Dir.unstub(:entries) + FileUtils.rm_rf path, :secure => true + rescue Errno::ENOENT + # nothing to do + end + end + end + + def make_absolute(path) PuppetSpec::Files.make_absolute(path) end + def self.make_absolute(path) + path = File.expand_path(path) + path[0] = 'c' if Puppet.features.microsoft_windows? + path + end + + def tmpfile(name, dir = nil) PuppetSpec::Files.tmpfile(name, dir) end + def self.tmpfile(name, dir = nil) + # Generate a temporary file, just for the name... + source = dir ? Tempfile.new(name, dir) : Tempfile.new(name) + path = source.path + source.close! + + record_tmp(File.expand_path(path)) + + path + end + + def file_containing(name, contents) PuppetSpec::Files.file_containing(name, contents) end + def self.file_containing(name, contents) + file = tmpfile(name) + File.open(file, 'wb') { |f| f.write(contents) } + file + end + + def tmpdir(name) PuppetSpec::Files.tmpdir(name) end + def self.tmpdir(name) + dir = Dir.mktmpdir(name) + + record_tmp(dir) + + dir + end + + def self.record_tmp(tmp) + # ...record it for cleanup, + $global_tempfiles ||= [] + $global_tempfiles << tmp + end +end diff --git a/spec/lib/puppet_spec/fixtures.rb b/spec/lib/puppet_spec/fixtures.rb new file mode 100755 index 0000000..7f6bc2a --- /dev/null +++ b/spec/lib/puppet_spec/fixtures.rb @@ -0,0 +1,28 @@ +module PuppetSpec::Fixtures + def fixtures(*rest) + File.join(PuppetSpec::FIXTURE_DIR, *rest) + end + def my_fixture_dir + callers = caller + while line = callers.shift do + next unless found = line.match(%r{/spec/(.*)_spec\.rb:}) + return fixtures(found[1]) + end + fail "sorry, I couldn't work out your path from the caller stack!" + end + def my_fixture(name) + file = File.join(my_fixture_dir, name) + unless File.readable? file then + fail Puppet::DevError, "fixture '#{name}' for #{my_fixture_dir} is not readable" + end + return file + end + def my_fixtures(glob = '*', flags = 0) + files = Dir.glob(File.join(my_fixture_dir, glob), flags) + unless files.length > 0 then + fail Puppet::DevError, "fixture '#{glob}' for #{my_fixture_dir} had no files!" + end + block_given? and files.each do |file| yield file end + files + end +end diff --git a/spec/lib/puppet_spec/matchers.rb b/spec/lib/puppet_spec/matchers.rb new file mode 100644 index 0000000..448bd18 --- /dev/null +++ b/spec/lib/puppet_spec/matchers.rb @@ -0,0 +1,120 @@ +require 'stringio' + +######################################################################## +# Backward compatibility for Jenkins outdated environment. +module RSpec + module Matchers + module BlockAliases + alias_method :to, :should unless method_defined? :to + alias_method :to_not, :should_not unless method_defined? :to_not + alias_method :not_to, :should_not unless method_defined? :not_to + end + end +end + + +######################################################################## +# Custom matchers... +RSpec::Matchers.define :have_matching_element do |expected| + match do |actual| + actual.any? { |item| item =~ expected } + end +end + + +RSpec::Matchers.define :exit_with do |expected| + actual = nil + match do |block| + begin + block.call + rescue SystemExit => e + actual = e.status + end + actual and actual == expected + end + failure_message_for_should do |block| + "expected exit with code #{expected} but " + + (actual.nil? ? " exit was not called" : "we exited with #{actual} instead") + end + failure_message_for_should_not do |block| + "expected that exit would not be called with #{expected}" + end + description do + "expect exit with #{expected}" + end +end + +class HavePrintedMatcher + attr_accessor :expected, :actual + + def initialize(expected) + case expected + when String, Regexp + @expected = expected + else + @expected = expected.to_s + end + end + + def matches?(block) + begin + $stderr = $stdout = StringIO.new + $stdout.set_encoding('UTF-8') if $stdout.respond_to?(:set_encoding) + block.call + $stdout.rewind + @actual = $stdout.read + ensure + $stdout = STDOUT + $stderr = STDERR + end + + if @actual then + case @expected + when String + @actual.include? @expected + when Regexp + @expected.match @actual + end + else + false + end + end + + def failure_message_for_should + if @actual.nil? then + "expected #{@expected.inspect}, but nothing was printed" + else + "expected #{@expected.inspect} to be printed; got:\n#{@actual}" + end + end + + def failure_message_for_should_not + "expected #{@expected.inspect} to not be printed; got:\n#{@actual}" + end + + def description + "expect #{@expected.inspect} to be printed" + end +end + +def have_printed(what) + HavePrintedMatcher.new(what) +end + +RSpec::Matchers.define :equal_attributes_of do |expected| + match do |actual| + actual.instance_variables.all? do |attr| + actual.instance_variable_get(attr) == expected.instance_variable_get(attr) + end + end +end + +RSpec::Matchers.define :be_one_of do |*expected| + match do |actual| + expected.include? actual + end + + failure_message_for_should do |actual| + "expected #{actual.inspect} to be one of #{expected.map(&:inspect).join(' or ')}" + end +end diff --git a/spec/lib/puppet_spec/modules.rb b/spec/lib/puppet_spec/modules.rb new file mode 100644 index 0000000..6835e44 --- /dev/null +++ b/spec/lib/puppet_spec/modules.rb @@ -0,0 +1,26 @@ +module PuppetSpec::Modules + class << self + def create(name, dir, options = {}) + module_dir = File.join(dir, name) + FileUtils.mkdir_p(module_dir) + + environment = options[:environment] + + if metadata = options[:metadata] + metadata[:source] ||= 'github' + metadata[:author] ||= 'puppetlabs' + metadata[:version] ||= '9.9.9' + metadata[:license] ||= 'to kill' + metadata[:dependencies] ||= [] + + metadata[:name] = "#{metadata[:author]}/#{name}" + + File.open(File.join(module_dir, 'metadata.json'), 'w') do |f| + f.write(metadata.to_pson) + end + end + + Puppet::Module.new(name, module_dir, environment) + end + end +end diff --git a/spec/lib/puppet_spec/pops.rb b/spec/lib/puppet_spec/pops.rb new file mode 100644 index 0000000..442c85b --- /dev/null +++ b/spec/lib/puppet_spec/pops.rb @@ -0,0 +1,16 @@ +module PuppetSpec::Pops + extend RSpec::Matchers::DSL + + # Checks if an Acceptor has a specific issue in its list of diagnostics + matcher :have_issue do |expected| + match do |actual| + actual.diagnostics.index { |i| i.issue == expected } != nil + end + failure_message_for_should do |actual| + "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to contain issue #{expected.issue_code}" + end + failure_message_for_should_not do |actual| + "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to not contain issue #{expected.issue_code}" + end + end +end diff --git a/spec/lib/puppet_spec/scope.rb b/spec/lib/puppet_spec/scope.rb new file mode 100644 index 0000000..c14ab47 --- /dev/null +++ b/spec/lib/puppet_spec/scope.rb @@ -0,0 +1,14 @@ + +module PuppetSpec::Scope + # Initialize a new scope suitable for testing. + # + def create_test_scope_for_node(node_name) + node = Puppet::Node.new(node_name) + compiler = Puppet::Parser::Compiler.new(node) + scope = Puppet::Parser::Scope.new(compiler) + scope.source = Puppet::Resource::Type.new(:node, node_name) + scope.parent = compiler.topscope + scope + end + +end
\ No newline at end of file diff --git a/spec/lib/puppet_spec/settings.rb b/spec/lib/puppet_spec/settings.rb new file mode 100644 index 0000000..f3dbc42 --- /dev/null +++ b/spec/lib/puppet_spec/settings.rb @@ -0,0 +1,15 @@ +module PuppetSpec::Settings + + # It would probably be preferable to refactor defaults.rb such that the real definitions of + # these settings were available as a variable, which was then accessible for use during tests. + # However, I'm not doing that yet because I don't want to introduce any additional moving parts + # to this already very large changeset. + # Would be nice to clean this up later. --cprice 2012-03-20 + TEST_APP_DEFAULT_DEFINITIONS = { + :name => { :default => "test", :desc => "name" }, + :logdir => { :type => :directory, :default => "test", :desc => "logdir" }, + :confdir => { :type => :directory, :default => "test", :desc => "confdir" }, + :vardir => { :type => :directory, :default => "test", :desc => "vardir" }, + :rundir => { :type => :directory, :default => "test", :desc => "rundir" }, + } +end diff --git a/spec/lib/puppet_spec/verbose.rb b/spec/lib/puppet_spec/verbose.rb new file mode 100755 index 0000000..d9834f2 --- /dev/null +++ b/spec/lib/puppet_spec/verbose.rb @@ -0,0 +1,9 @@ +# Support code for running stuff with warnings disabled. +module Kernel + def with_verbose_disabled + verbose, $VERBOSE = $VERBOSE, nil + result = yield + $VERBOSE = verbose + return result + end +end |