]> gitweb.fluxo.info Git - puppet-stdlib.git/commitdiff
Copied function test scaffolding from puppet.
authorKen Barber <ken@bob.sh>
Wed, 29 Jun 2011 11:25:43 +0000 (12:25 +0100)
committerKen Barber <ken@bob.sh>
Wed, 29 Jun 2011 11:25:43 +0000 (12:25 +0100)
Rakefile [new file with mode: 0644]
spec/lib/puppet_spec/files.rb [new file with mode: 0755]
spec/lib/puppet_spec/fixtures.rb [new file with mode: 0755]
spec/lib/puppet_spec/matchers.rb [new file with mode: 0644]
spec/lib/puppet_spec/verbose.rb [new file with mode: 0755]
spec/monkey_patches/alias_should_to_must.rb [new file with mode: 0755]
spec/monkey_patches/publicize_methods.rb [new file with mode: 0755]
spec/spec.opts [new file with mode: 0644]
spec/spec_helper.rb [new file with mode: 0755]

diff --git a/Rakefile b/Rakefile
new file mode 100644 (file)
index 0000000..01b2a31
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,16 @@
+require 'rake'
+require 'rspec/core/rake_task'
+
+task :default => [:test]
+
+desc 'Run RSpec'
+RSpec::Core::RakeTask.new(:test) do |t|
+  t.pattern = 'spec/{unit}/**/*.rb'
+  t.rspec_opts = ['--color']
+end
+
+desc 'Generate code coverage'
+RSpec::Core::RakeTask.new(:coverage) do |t|
+  t.rcov = true
+  t.rcov_opts = ['--exclude', 'spec']
+end
diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb
new file mode 100755 (executable)
index 0000000..30fb4fc
--- /dev/null
@@ -0,0 +1,53 @@
+require 'fileutils'
+require 'tempfile'
+
+# A support module for testing files.
+module PuppetSpec::Files
+  # This code exists only to support tests that run as root, pretty much.
+  # Once they have finally been eliminated this can all go... --daniel 2011-04-08
+  if Puppet.features.posix? then
+    def self.in_tmp(path)
+      path =~ /^\/tmp/ or path =~ /^\/var\/folders/
+    end
+  elsif Puppet.features.microsoft_windows?
+    def self.in_tmp(path)
+      tempdir = File.expand_path(File.join(Dir::LOCAL_APPDATA, "Temp"))
+      path =~ /^#{tempdir}/
+    end
+  else
+    fail "Help! Can't find in_tmp for this platform"
+  end
+
+  def self.cleanup
+    $global_tempfiles ||= []
+    while path = $global_tempfiles.pop do
+      fail "Not deleting tmpfile #{path} outside regular tmpdir" unless in_tmp(path)
+
+      begin
+        FileUtils.rm_r path, :secure => true
+      rescue Errno::ENOENT
+        # nothing to do
+      end
+    end
+  end
+
+  def tmpfile(name)
+    # Generate a temporary file, just for the name...
+    source = Tempfile.new(name)
+    path = source.path
+    source.close!
+
+    # ...record it for cleanup,
+    $global_tempfiles ||= []
+    $global_tempfiles << File.expand_path(path)
+
+    # ...and bam.
+    path
+  end
+
+  def tmpdir(name)
+    path = tmpfile(name)
+    FileUtils.mkdir_p(path)
+    path
+  end
+end
diff --git a/spec/lib/puppet_spec/fixtures.rb b/spec/lib/puppet_spec/fixtures.rb
new file mode 100755 (executable)
index 0000000..7f6bc2a
--- /dev/null
@@ -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 (file)
index 0000000..77f5803
--- /dev/null
@@ -0,0 +1,87 @@
+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
+
+
+RSpec::Matchers.define :have_printed do |expected|
+  match do |block|
+    $stderr = $stdout = StringIO.new
+
+    begin
+      block.call
+    ensure
+      $stdout.rewind
+      @actual = $stdout.read
+
+      $stdout = STDOUT
+      $stderr = STDERR
+    end
+
+    if @actual then
+      case expected
+      when String
+        @actual.include? expected
+      when Regexp
+        expected.match @actual
+      else
+        raise ArgumentError, "No idea how to match a #{@actual.class.name}"
+      end
+    end
+  end
+
+  failure_message_for_should do |actual|
+    if actual.nil? then
+      "expected #{expected.inspect}, but nothing was printed"
+    else
+      "expected #{expected.inspect} to be printed; got:\n#{actual}"
+    end
+  end
+
+  description do
+    "expect #{expected.inspect} to be printed"
+  end
+
+  diffable
+end
diff --git a/spec/lib/puppet_spec/verbose.rb b/spec/lib/puppet_spec/verbose.rb
new file mode 100755 (executable)
index 0000000..d9834f2
--- /dev/null
@@ -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
diff --git a/spec/monkey_patches/alias_should_to_must.rb b/spec/monkey_patches/alias_should_to_must.rb
new file mode 100755 (executable)
index 0000000..1a11117
--- /dev/null
@@ -0,0 +1,8 @@
+require 'rspec'
+
+class Object
+  # This is necessary because the RAL has a 'should'
+  # method.
+  alias :must :should
+  alias :must_not :should_not
+end
diff --git a/spec/monkey_patches/publicize_methods.rb b/spec/monkey_patches/publicize_methods.rb
new file mode 100755 (executable)
index 0000000..b39e9c0
--- /dev/null
@@ -0,0 +1,11 @@
+# Some monkey-patching to allow us to test private methods.
+class Class
+    def publicize_methods(*methods)
+        saved_private_instance_methods = methods.empty? ? self.private_instance_methods : methods
+
+        self.class_eval { public(*saved_private_instance_methods) }
+        yield
+        self.class_eval { private(*saved_private_instance_methods) }
+    end
+end
+
diff --git a/spec/spec.opts b/spec/spec.opts
new file mode 100644 (file)
index 0000000..425f0ed
--- /dev/null
@@ -0,0 +1,4 @@
+--format
+s
+--colour
+--backtrace
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100755 (executable)
index 0000000..fdc04bc
--- /dev/null
@@ -0,0 +1,78 @@
+dir = File.expand_path(File.dirname(__FILE__))
+$LOAD_PATH.unshift File.join(dir, 'lib')
+
+p dir
+
+# Don't want puppet getting the command line arguments for rake or autotest
+ARGV.clear
+
+require 'puppet'
+require 'mocha'
+gem 'rspec', '>=2.0.0'
+require 'rspec/expectations'
+
+# So everyone else doesn't have to include this base constant.
+module PuppetSpec
+  FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR)
+end
+
+require 'pathname'
+require 'tmpdir'
+
+require 'puppet_spec/verbose'
+require 'puppet_spec/files'
+require 'puppet_spec/fixtures'
+require 'puppet_spec/matchers'
+require 'monkey_patches/alias_should_to_must'
+require 'monkey_patches/publicize_methods'
+
+Pathname.glob("#{dir}/shared_behaviours/**/*.rb") do |behaviour|
+  require behaviour.relative_path_from(Pathname.new(dir))
+end
+
+RSpec.configure do |config|
+  include PuppetSpec::Fixtures
+
+  config.mock_with :mocha
+
+  config.before :each do
+    GC.disable
+
+    # these globals are set by Application
+    $puppet_application_mode = nil
+    $puppet_application_name = nil
+
+    # REVISIT: I think this conceals other bad tests, but I don't have time to
+    # fully diagnose those right now.  When you read this, please come tell me
+    # I suck for letting this float. --daniel 2011-04-21
+    Signal.stubs(:trap)
+
+    # Set the confdir and vardir to gibberish so that tests
+    # have to be correctly mocked.
+    Puppet[:confdir] = "/dev/null"
+    Puppet[:vardir] = "/dev/null"
+
+    # Avoid opening ports to the outside world
+    Puppet.settings[:bindaddress] = "127.0.0.1"
+
+    @logs = []
+    Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs))
+
+    @log_level = Puppet::Util::Log.level
+  end
+
+  config.after :each do
+    Puppet.settings.clear
+    Puppet::Node::Environment.clear
+    Puppet::Util::Storage.clear
+    Puppet::Util::ExecutionStub.reset
+
+    PuppetSpec::Files.cleanup
+
+    @logs.clear
+    Puppet::Util::Log.close_all
+    Puppet::Util::Log.level = @log_level
+
+    GC.enable
+  end
+end