Commit 49c64c08 authored by Stefan Schulte's avatar Stefan Schulte
Browse files

Use puppetlabs_spec_helper

PuppetLabs has released a seperate gem to make writing spec tests easier
(puppetlabs_spec_helper). Using this gem makes a lot of files obsolete
that were initially copied form the puppetlabs/puppet project.
parent 6a15db32
......@@ -37,3 +37,9 @@ or - if you want to make sure a key is deleted - specify
}
The `name` of the `rpmkey` resource has to be the keyID of the gpg key.
Running the tests
-----------------
This project requires the `puppetlabs_spec_helper` gem (available on rubygems.org)
to run the spec tests. You can run them by executing `rake spec`.
require 'rubygems'
require 'puppetlabs_spec_helper/rake_tasks'
module PuppetSpec::Compiler
def compile_to_catalog(string)
Puppet[:code] = string
Puppet::Parser::Compiler.compile(Puppet::Node.new('foonode'))
end
end
# 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
dir = PuppetSpec::Files.tmpdir('puppet-sqlite')
Puppet[:dbadapter] = 'sqlite3'
Puppet[:dblocation] = (dir + 'storeconfigs.sqlite').to_s
Puppet[:railslog] = '/dev/null'
Puppet::Rails.init
end
require 'fileutils'
require 'tempfile'
require 'pathname'
# 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
def self.in_tmp(path)
tempdir = Dir.tmpdir
Pathname.new(path).ascend do |dir|
return true if File.identical?(tempdir, dir)
end
false
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 make_absolute(path)
path = File.expand_path(path)
path[0] = 'c' if Puppet.features.microsoft_windows?
path
end
def tmpfile(name) PuppetSpec::Files.tmpfile(name) end
def self.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) PuppetSpec::Files.tmpdir(name) end
def self.tmpdir(name)
path = tmpfile(name)
FileUtils.mkdir_p(path)
path
end
end
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
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
module PuppetSpec::Modules
class << self
def create(name, dir, options = {})
module_dir = File.join(dir, name)
FileUtils.mkdir_p(module_dir)
environment = Puppet::Node::Environment.new(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, :environment => environment, :path => module_dir)
end
end
end
# 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
require 'rspec'
class Object
# This is necessary because the RAL has a 'should'
# method.
alias :must :should
alias :must_not :should_not
end
# 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
shared_examples_for "all parsedfile providers" do |provider, *files|
if files.empty? then
files = my_fixtures
end
files.flatten.each do |file|
it "should rewrite #{file} reasonably unchanged" do
provider.stubs(:default_target).returns(file)
provider.prefetch
text = provider.to_file(provider.target_records(file))
text.gsub!(/^# HEADER.+\n/, '')
oldlines = File.readlines(file)
newlines = text.chomp.split "\n"
oldlines.zip(newlines).each do |old, new|
new.gsub(/\s+/, '').should == old.chomp.gsub(/\s+/, '')
end
end
end
end
shared_examples_for "an indirector face" do
[:find, :search, :save, :destroy, :info].each do |action|
it { should be_action action }
it { should respond_to action }
end
end
# encoding: UTF-8
shared_examples_for "documentation on faces" do
defined?(Attrs) or
Attrs = [:summary, :description, :examples, :short_description, :notes, :author]
defined?(SingleLineAttrs) or
SingleLineAttrs = [:summary, :author]
# Simple, procedural tests that apply to a bunch of methods.
Attrs.each do |attr|
it "should accept a #{attr}" do
expect { subject.send("#{attr}=", "hello") }.not_to raise_error
subject.send(attr).should == "hello"
end
it "should accept a long (single line) value for #{attr}" do
text = "I never know when to stop with the word banana" + ("na" * 1000)
expect { subject.send("#{attr}=", text) }.to_not raise_error
subject.send(attr).should == text
end
end
Attrs.each do |getter|
setter = "#{getter}=".to_sym
context "#{getter}" do
it "should strip leading whitespace on a single line" do
subject.send(setter, " death to whitespace")
subject.send(getter).should == "death to whitespace"
end
it "should strip trailing whitespace on a single line" do
subject.send(setter, "death to whitespace ")
subject.send(getter).should == "death to whitespace"
end
it "should strip whitespace at both ends at once" do
subject.send(setter, " death to whitespace ")
subject.send(getter).should == "death to whitespace"
end
multiline_text = "with\nnewlines"
if SingleLineAttrs.include? getter then
it "should not accept multiline values" do
expect { subject.send(setter, multiline_text) }.
to raise_error ArgumentError, /#{getter} should be a single line/
subject.send(getter).should be_nil
end
else
it "should accept multiline values" do
expect { subject.send(setter, multiline_text) }.not_to raise_error
subject.send(getter).should == multiline_text
end
[1, 2, 4, 7, 25].each do |length|
context "#{length} chars indent" do
indent = ' ' * length
it "should strip leading whitespace on multiple lines" do
text = "this\nis\the\final\outcome"
subject.send(setter, text.gsub(/^/, indent))
subject.send(getter).should == text
end
it "should not remove formatting whitespace, only global indent" do
text = "this\n is\n the\n ultimate\ntest\n"
subject.send(setter, text.gsub(/^/, indent))
subject.send(getter).should == text
end
end
end
it "should strip whitespace with a blank line" do
subject.send(setter, " this\n\n should outdent\n")
subject.send(getter).should == "this\n\nshould outdent\n"
end
end
end
end
describe "#short_description" do
it "should return the set value if set after description" do
subject.description = "hello\ngoodbye"
subject.short_description = "whatever"
subject.short_description.should == "whatever"
end
it "should return the set value if set before description" do
subject.short_description = "whatever"
subject.description = "hello\ngoodbye"
subject.short_description.should == "whatever"
end
it "should return nothing if not set and no description" do
subject.short_description.should be_nil
end
it "should return the first paragraph of description if not set (where it is one line long)" do
subject.description = "hello"
subject.short_description.should == subject.description
end
it "should return the first paragraph of description if not set (where there is no paragraph break)" do
subject.description = "hello\ngoodbye"
subject.short_description.should == subject.description
end
it "should return the first paragraph of description if not set (where there is a paragraph break)" do
subject.description = "hello\ngoodbye\n\nmore\ntext\nhere\n\nfinal\nparagraph"
subject.short_description.should == "hello\ngoodbye"
end
it "should trim a very, very long first paragraph and add ellipsis" do
line = "this is a very, very, very long long line full of text\n"
subject.description = line * 20 + "\n\nwhatever, dude."
subject.short_description.should == (line * 5).chomp + ' [...]'
end
it "should trim a very very long only paragraph even if it is followed by a new paragraph" do
line = "this is a very, very, very long long line full of text\n"
subject.description = line * 20
subject.short_description.should == (line * 5).chomp + ' [...]'
end
end
describe "multiple authors" do
authors = %w{John Paul George Ringo}
context "in the DSL" do
it "should support multiple authors" do
authors.each {|name| subject.author name }
subject.authors.should =~ authors
subject.author.should == authors.join("\n")
end
it "should reject author as an array" do
expect { subject.author ["Foo", "Bar"] }.
to raise_error ArgumentError, /author must be a string/
end
end
context "#author=" do
it "should accept a single name" do
subject.author = "Fred"
subject.author.should == "Fred"
end
it "should accept an array of names" do
subject.author = authors
subject.authors.should =~ authors
subject.author.should == authors.join("\n")
end
it "should not append when set multiple times" do
subject.author = "Fred"
subject.author = "John"
subject.author.should == "John"
end
it "should reject arrays with embedded newlines" do
expect { subject.author = ["Fred\nJohn"] }.
to raise_error ArgumentError, /author should be a single line/
end
end
end
describe "#license" do
it "should default to reserving rights" do
subject.license.should =~ /All Rights Reserved/
end
it "should accept an arbitrary license string on the object" do
subject.license = "foo"
subject.license.should == "foo"
end
it "should accept symbols to specify existing licenses..."
end
describe "#copyright" do
it "should fail with just a name" do
expect { subject.copyright("invalid") }.
to raise_error ArgumentError, /copyright takes the owners names, then the years covered/
end
[1997, "1997"].each do |year|
it "should accept an entity name and a #{year.class.name} year" do
subject.copyright("me", year)
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /#{year}/
end
it "should accept multiple entity names and a #{year.class.name} year" do
subject.copyright ["me", "you"], year
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /\byou\b/
subject.copyright.should =~ /#{year}/
end
end
["1997-2003", "1997 - 2003", 1997..2003].each do |range|
it "should accept a #{range.class.name} range of years" do
subject.copyright("me", range)
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /1997-2003/
end
it "should accept a #{range.class.name} range of years" do
subject.copyright ["me", "you"], range
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /\byou\b/
subject.copyright.should =~ /1997-2003/
end
end
[[1997, 2003], ["1997", 2003], ["1997", "2003"]].each do |input|
it "should accept the set of years #{input.inspect} in an array" do
subject.copyright "me", input
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /1997, 2003/
end
it "should accept the set of years #{input.inspect} in an array" do
subject.copyright ["me", "you"], input
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /\byou\b/
subject.copyright.should =~ /1997, 2003/
end
end
it "should warn if someone does math accidentally on the range of years" do
expect { subject.copyright "me", 1997-2003 }.
to raise_error ArgumentError, /copyright with a year before 1970 is very strange; did you accidentally add or subtract two years\?/
end
it "should accept complex copyright years" do
years = [1997, 1999, 2000..2002, 2005].reverse
subject.copyright "me", years
subject.copyright.should =~ /\bme\b/
subject.copyright.should =~ /1997, 1999, 2000-2002, 2005/
end
end
# Things that are automatically generated.
[:name, :options, :synopsis].each do |attr|
describe "##{attr}" do
it "should not allow you to set #{attr}" do
subject.should_not respond_to :"#{attr}="
end
it "should have a #{attr}" do
subject.send(attr).should_not be_nil
end
it "'s #{attr} should not be empty..." do
subject.send(attr).should_not == ''
end
end
end
end
#!/usr/bin/env rspec
shared_examples_for "Puppet::Indirector::FileServerTerminus" do
# This only works if the shared behaviour is included before
# the 'before' block in the including context.
before do
Puppet::FileServing::Configuration.instance_variable_set(:@configuration, nil)
FileTest.stubs(:exists?).returns true
FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true)
@path = Tempfile.new("file_server_testing")
path = @path.path
@path.close!
@path = path
Dir.mkdir(@path)