diff --git a/spec/integration/provider/mailalias/aliases_spec.rb b/spec/integration/provider/mailalias/aliases_spec.rb index 8106c2cb5..0511205f2 100755 --- a/spec/integration/provider/mailalias/aliases_spec.rb +++ b/spec/integration/provider/mailalias/aliases_spec.rb @@ -1,25 +1,25 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' -require 'puppettest' require 'puppettest/support/utils' require 'puppettest/fileparsing' provider_class = Puppet::Type.type(:mailalias).provider(:aliases) describe provider_class do include PuppetTest include PuppetTest::FileParsing + include PuppetTest::Support::Utils before :each do @provider = provider_class end # #1560 - PuppetTest.fakedata("data/providers/mailalias/aliases").each { |file| - it "should be able to parse the examples in #{file}" do + it "should be able to parse the mailalias examples" do + fakedata("data/providers/mailalias/aliases").each { |file| fakedataparse(file) - end - } + } + end end diff --git a/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb index 15a7cd0ac..3762b7033 100644 --- a/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb +++ b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb @@ -1,47 +1,46 @@ dir = File.expand_path(File.dirname(__FILE__)) [ "#{dir}/../../lib", "#{dir}/../../test/lib"].each do |dir| fulldir = File.expand_path(dir) $LOAD_PATH.unshift(fulldir) unless $LOAD_PATH.include?(fulldir) end require 'spec' -require 'puppettest' require 'puppettest/runnable_test' module Spec module Runner class ExampleGroupRunner def run prepare success = true example_groups.each do |example_group| unless example_group.runnable? warn "Skipping unsuitable example group #{example_group.description}: #{example_group.messages.join(", ")}" next end success = success & example_group.run(@options) Puppet.settings.clear end return success ensure finish end end end end module Spec module Example class ExampleGroup extend PuppetTest::RunnableTest end end end module Test module Unit class TestCase extend PuppetTest::RunnableTest end end end diff --git a/spec/monkey_patches/publicize_methods.rb b/spec/monkey_patches/publicize_methods.rb new file mode 100644 index 000000000..b39e9c002 --- /dev/null +++ b/spec/monkey_patches/publicize_methods.rb @@ -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_helper.rb b/spec/spec_helper.rb index 539ae2040..ab7ff6caf 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,97 +1,75 @@ unless defined?(SPEC_HELPER_IS_LOADED) SPEC_HELPER_IS_LOADED = 1 dir = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift("#{dir}/") $LOAD_PATH.unshift("#{dir}/lib") # a spec-specific test lib dir $LOAD_PATH.unshift("#{dir}/../lib") -$LOAD_PATH.unshift("#{dir}/../test/lib") # Add the old test dir, so that we can still find our local mocha and spec -# include any gems in vendor/gems -Dir["#{dir}/../vendor/gems/**"].each do |path| - libpath = File.join(path, "lib") - if File.directory?(libpath) - $LOAD_PATH.unshift(libpath) - else - $LOAD_PATH.unshift(path) - end -end - -require 'puppettest' -require 'puppettest/runnable_test' +require 'puppet' require 'mocha' gem 'rspec', '>=1.2.9' require 'spec/autorun' # 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 -# load any monkey-patches -Dir["#{dir}/monkey_patches/*.rb"].map { |file| require file } +require 'monkey_patches/alias_should_to_must' +require 'monkey_patches/add_confine_and_runnable_to_rspec_dsl' +require 'monkey_patches/publicize_methods' Spec::Runner.configure do |config| config.mock_with :mocha -# config.prepend_before :all do -# setup_mocks_for_rspec -# setup if respond_to? :setup -# end -# config.prepend_after :each do Puppet.settings.clear Puppet::Node::Environment.clear Puppet::Util::Storage.clear if defined?($tmpfiles) $tmpfiles.each do |file| file = File.expand_path(file) if Puppet.features.posix? and file !~ /^\/tmp/ and file !~ /^\/var\/folders/ puts "Not deleting tmpfile #{file} outside of /tmp or /var/folders" next elsif Puppet.features.microsoft_windows? tempdir = File.expand_path(File.join(Dir::LOCAL_APPDATA, "Temp")) if file !~ /^#{tempdir}/ puts "Not deleting tmpfile #{file} outside of #{tempdir}" next end end if FileTest.exist?(file) system("chmod -R 755 '#{file}'") system("rm -rf '#{file}'") end end $tmpfiles.clear end @logs.clear Puppet::Util::Log.close_all end config.prepend_before :each do # these globals are set by Application $puppet_application_mode = nil $puppet_application_name = nil # 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(@logs) end end -# We need this because the RAL uses 'should' as a method. This -# allows us the same behaviour but with a different method name. -class Object - alias :must :should -end - end diff --git a/spec/unit/network/http/webrick/rest_spec.rb b/spec/unit/network/http/webrick/rest_spec.rb index aa2b93176..b00c62dc4 100755 --- a/spec/unit/network/http/webrick/rest_spec.rb +++ b/spec/unit/network/http/webrick/rest_spec.rb @@ -1,180 +1,181 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../../spec_helper' require 'puppet/network/http' +require 'webrick' require 'puppet/network/http/webrick/rest' describe Puppet::Network::HTTP::WEBrickREST do it "should include the Puppet::Network::HTTP::Handler module" do Puppet::Network::HTTP::WEBrickREST.ancestors.should be_include(Puppet::Network::HTTP::Handler) end describe "when initializing" do it "should call the Handler's initialization hook with its provided arguments as the server and handler" do Puppet::Network::HTTP::WEBrickREST.any_instance.expects(:initialize_for_puppet).with(:server => "my", :handler => "arguments") Puppet::Network::HTTP::WEBrickREST.new("my", "arguments") end end describe "when receiving a request" do before do @request = stub('webrick http request', :query => {}, :peeraddr => %w{eh boo host ip}, :client_cert => nil) @response = stub('webrick http response', :status= => true, :body= => true) @model_class = stub('indirected model class') @webrick = stub('webrick http server', :mount => true, :[] => {}) Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@model_class) @handler = Puppet::Network::HTTP::WEBrickREST.new(@webrick, :foo) end it "should delegate its :service method to its :process method" do @handler.expects(:process).with(@request, @response).returns "stuff" @handler.service(@request, @response).should == "stuff" end describe "when using the Handler interface" do it "should use the 'accept' request parameter as the Accept header" do @request.expects(:[]).with("accept").returns "foobar" @handler.accept_header(@request).should == "foobar" end it "should use the 'content-type' request header as the Content-Type header" do @request.expects(:[]).with("content-type").returns "foobar" @handler.content_type_header(@request).should == "foobar" end it "should use the request method as the http method" do @request.expects(:request_method).returns "FOO" @handler.http_method(@request).should == "FOO" end it "should return the request path as the path" do @request.expects(:path).returns "/foo/bar" @handler.path(@request).should == "/foo/bar" end it "should return the request body as the body" do @request.expects(:body).returns "my body" @handler.body(@request).should == "my body" end it "should set the response's 'content-type' header when setting the content type" do @response.expects(:[]=).with("content-type", "text/html") @handler.set_content_type(@response, "text/html") end it "should set the status and body on the response when setting the response for a successful query" do @response.expects(:status=).with 200 @response.expects(:body=).with "mybody" @handler.set_response(@response, "mybody", 200) end describe "when the result is a File" do before(:each) do stat = stub 'stat', :size => 100 @file = stub 'file', :stat => stat, :path => "/tmp/path" @file.stubs(:is_a?).with(File).returns(true) end it "should serve it" do @response.stubs(:[]=) @response.expects(:status=).with 200 @response.expects(:body=).with @file @handler.set_response(@response, @file, 200) end it "should set the Content-Length header" do @response.expects(:[]=).with('content-length', 100) @handler.set_response(@response, @file, 200) end end it "should set the status and message on the response when setting the response for a failed query" do @response.expects(:status=).with 400 @response.expects(:reason_phrase=).with "mybody" @handler.set_response(@response, "mybody", 400) end end describe "and determining the request parameters" do it "should include the HTTP request parameters, with the keys as symbols" do @request.stubs(:query).returns("foo" => "baz", "bar" => "xyzzy") result = @handler.params(@request) result[:foo].should == "baz" result[:bar].should == "xyzzy" end it "should CGI-decode the HTTP parameters" do encoding = CGI.escape("foo bar") @request.expects(:query).returns('foo' => encoding) result = @handler.params(@request) result[:foo].should == "foo bar" end it "should convert the string 'true' to the boolean" do @request.expects(:query).returns('foo' => "true") result = @handler.params(@request) result[:foo].should be_true end it "should convert the string 'false' to the boolean" do @request.expects(:query).returns('foo' => "false") result = @handler.params(@request) result[:foo].should be_false end it "should YAML-load and CGI-decode values that are YAML-encoded" do escaping = CGI.escape(YAML.dump(%w{one two})) @request.expects(:query).returns('foo' => escaping) result = @handler.params(@request) result[:foo].should == %w{one two} end it "should not allow clients to set the node via the request parameters" do @request.stubs(:query).returns("node" => "foo") @handler.stubs(:resolve_node) @handler.params(@request)[:node].should be_nil end it "should not allow clients to set the IP via the request parameters" do @request.stubs(:query).returns("ip" => "foo") @handler.params(@request)[:ip].should_not == "foo" end it "should pass the client's ip address to model find" do @request.stubs(:peeraddr).returns(%w{noidea dunno hostname ipaddress}) @handler.params(@request)[:ip].should == "ipaddress" end it "should set 'authenticated' to true if a certificate is present" do cert = stub 'cert', :subject => [%w{CN host.domain.com}] @request.stubs(:client_cert).returns cert @handler.params(@request)[:authenticated].should be_true end it "should set 'authenticated' to false if no certificate is present" do @request.stubs(:client_cert).returns nil @handler.params(@request)[:authenticated].should be_false end it "should pass the client's certificate name to model method if a certificate is present" do cert = stub 'cert', :subject => [%w{CN host.domain.com}] @request.stubs(:client_cert).returns cert @handler.params(@request)[:node].should == "host.domain.com" end it "should resolve the node name with an ip address look-up if no certificate is present" do @request.stubs(:client_cert).returns nil @handler.expects(:resolve_node).returns(:resolved_node) @handler.params(@request)[:node].should == :resolved_node end end end end diff --git a/spec/unit/parser/lexer_spec.rb b/spec/unit/parser/lexer_spec.rb index 7e51423f4..b27980bf2 100755 --- a/spec/unit/parser/lexer_spec.rb +++ b/spec/unit/parser/lexer_spec.rb @@ -1,656 +1,655 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/parser/lexer' # This is a special matcher to match easily lexer output Spec::Matchers.define :be_like do |*expected| match do |actual| expected.zip(actual).all? { |e,a| !e or a[0] == e or (e.is_a? Array and a[0] == e[0] and (a[1] == e[1] or (a[1].is_a?(Hash) and a[1][:value] == e[1]))) } end end __ = nil describe Puppet::Parser::Lexer do describe "when reading strings" do before { @lexer = Puppet::Parser::Lexer.new } it "should increment the line count for every carriage return in the string" do @lexer.line = 10 @lexer.string = "this\nis\natest'" @lexer.slurpstring("'") @lexer.line.should == 12 end it "should not increment the line count for escapes in the string" do @lexer.line = 10 @lexer.string = "this\\nis\\natest'" @lexer.slurpstring("'") @lexer.line.should == 10 end end end describe Puppet::Parser::Lexer::Token do before do @token = Puppet::Parser::Lexer::Token.new(%r{something}, :NAME) end [:regex, :name, :string, :skip, :incr_line, :skip_text, :accumulate].each do |param| it "should have a #{param.to_s} reader" do @token.should be_respond_to(param) end it "should have a #{param.to_s} writer" do @token.should be_respond_to(param.to_s + "=") end end end describe Puppet::Parser::Lexer::Token, "when initializing" do it "should create a regex if the first argument is a string" do Puppet::Parser::Lexer::Token.new("something", :NAME).regex.should == %r{something} end it "should set the string if the first argument is one" do Puppet::Parser::Lexer::Token.new("something", :NAME).string.should == "something" end it "should set the regex if the first argument is one" do Puppet::Parser::Lexer::Token.new(%r{something}, :NAME).regex.should == %r{something} end end describe Puppet::Parser::Lexer::TokenList do before do @list = Puppet::Parser::Lexer::TokenList.new end it "should have a method for retrieving tokens by the name" do token = @list.add_token :name, "whatever" @list[:name].should equal(token) end it "should have a method for retrieving string tokens by the string" do token = @list.add_token :name, "whatever" @list.lookup("whatever").should equal(token) end it "should add tokens to the list when directed" do token = @list.add_token :name, "whatever" @list[:name].should equal(token) end it "should have a method for adding multiple tokens at once" do @list.add_tokens "whatever" => :name, "foo" => :bar @list[:name].should_not be_nil @list[:bar].should_not be_nil end it "should fail to add tokens sharing a name with an existing token" do @list.add_token :name, "whatever" lambda { @list.add_token :name, "whatever" }.should raise_error(ArgumentError) end it "should set provided options on tokens being added" do token = @list.add_token :name, "whatever", :skip_text => true token.skip_text.should == true end it "should define any provided blocks as a :convert method" do token = @list.add_token(:name, "whatever") do "foo" end token.convert.should == "foo" end it "should store all string tokens in the :string_tokens list" do one = @list.add_token(:name, "1") @list.string_tokens.should be_include(one) end it "should store all regex tokens in the :regex_tokens list" do one = @list.add_token(:name, %r{one}) @list.regex_tokens.should be_include(one) end it "should not store string tokens in the :regex_tokens list" do one = @list.add_token(:name, "1") @list.regex_tokens.should_not be_include(one) end it "should not store regex tokens in the :string_tokens list" do one = @list.add_token(:name, %r{one}) @list.string_tokens.should_not be_include(one) end it "should sort the string tokens inversely by length when asked" do one = @list.add_token(:name, "1") two = @list.add_token(:other, "12") @list.sort_tokens @list.string_tokens.should == [two, one] end end describe Puppet::Parser::Lexer::TOKENS do before do @lexer = Puppet::Parser::Lexer.new end { :LBRACK => '[', :RBRACK => ']', :LBRACE => '{', :RBRACE => '}', :LPAREN => '(', :RPAREN => ')', :EQUALS => '=', :ISEQUAL => '==', :GREATEREQUAL => '>=', :GREATERTHAN => '>', :LESSTHAN => '<', :LESSEQUAL => '<=', :NOTEQUAL => '!=', :NOT => '!', :COMMA => ',', :DOT => '.', :COLON => ':', :AT => '@', :LLCOLLECT => '<<|', :RRCOLLECT => '|>>', :LCOLLECT => '<|', :RCOLLECT => '|>', :SEMIC => ';', :QMARK => '?', :BACKSLASH => '\\', :FARROW => '=>', :PARROW => '+>', :APPENDS => '+=', :PLUS => '+', :MINUS => '-', :DIV => '/', :TIMES => '*', :LSHIFT => '<<', :RSHIFT => '>>', :MATCH => '=~', :NOMATCH => '!~', :IN_EDGE => '->', :OUT_EDGE => '<-', :IN_EDGE_SUB => '~>', :OUT_EDGE_SUB => '<~', }.each do |name, string| it "should have a token named #{name.to_s}" do Puppet::Parser::Lexer::TOKENS[name].should_not be_nil end it "should match '#{string}' for the token #{name.to_s}" do Puppet::Parser::Lexer::TOKENS[name].string.should == string end end { "case" => :CASE, "class" => :CLASS, "default" => :DEFAULT, "define" => :DEFINE, "import" => :IMPORT, "if" => :IF, "elsif" => :ELSIF, "else" => :ELSE, "inherits" => :INHERITS, "node" => :NODE, "and" => :AND, "or" => :OR, "undef" => :UNDEF, "false" => :FALSE, "true" => :TRUE, "in" => :IN, }.each do |string, name| it "should have a keyword named #{name.to_s}" do Puppet::Parser::Lexer::KEYWORDS[name].should_not be_nil end it "should have the keyword for #{name.to_s} set to #{string}" do Puppet::Parser::Lexer::KEYWORDS[name].string.should == string end end # These tokens' strings don't matter, just that the tokens exist. [:STRING, :DQPRE, :DQMID, :DQPOST, :BOOLEAN, :NAME, :NUMBER, :COMMENT, :MLCOMMENT, :RETURN, :SQUOTE, :DQUOTE, :VARIABLE].each do |name| it "should have a token named #{name.to_s}" do Puppet::Parser::Lexer::TOKENS[name].should_not be_nil end end end describe Puppet::Parser::Lexer::TOKENS[:CLASSNAME] do before { @token = Puppet::Parser::Lexer::TOKENS[:CLASSNAME] } it "should match against lower-case alpha-numeric terms separated by double colons" do @token.regex.should =~ "one::two" end it "should match against many lower-case alpha-numeric terms separated by double colons" do @token.regex.should =~ "one::two::three::four::five" end it "should match against lower-case alpha-numeric terms prefixed by double colons" do @token.regex.should =~ "::one" end end describe Puppet::Parser::Lexer::TOKENS[:CLASSREF] do before { @token = Puppet::Parser::Lexer::TOKENS[:CLASSREF] } it "should match against single upper-case alpha-numeric terms" do @token.regex.should =~ "One" end it "should match against upper-case alpha-numeric terms separated by double colons" do @token.regex.should =~ "One::Two" end it "should match against many upper-case alpha-numeric terms separated by double colons" do @token.regex.should =~ "One::Two::Three::Four::Five" end it "should match against upper-case alpha-numeric terms prefixed by double colons" do @token.regex.should =~ "::One" end end describe Puppet::Parser::Lexer::TOKENS[:NAME] do before { @token = Puppet::Parser::Lexer::TOKENS[:NAME] } it "should match against lower-case alpha-numeric terms" do @token.regex.should =~ "one-two" end it "should return itself and the value if the matched term is not a keyword" do Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(nil) @token.convert(stub("lexer"), "myval").should == [Puppet::Parser::Lexer::TOKENS[:NAME], "myval"] end it "should return the keyword token and the value if the matched term is a keyword" do keyword = stub 'keyword', :name => :testing Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword) @token.convert(stub("lexer"), "myval").should == [keyword, "myval"] end it "should return the BOOLEAN token and 'true' if the matched term is the string 'true'" do keyword = stub 'keyword', :name => :TRUE Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword) @token.convert(stub('lexer'), "true").should == [Puppet::Parser::Lexer::TOKENS[:BOOLEAN], true] end it "should return the BOOLEAN token and 'false' if the matched term is the string 'false'" do keyword = stub 'keyword', :name => :FALSE Puppet::Parser::Lexer::KEYWORDS.expects(:lookup).returns(keyword) @token.convert(stub('lexer'), "false").should == [Puppet::Parser::Lexer::TOKENS[:BOOLEAN], false] end end describe Puppet::Parser::Lexer::TOKENS[:NUMBER] do before do @token = Puppet::Parser::Lexer::TOKENS[:NUMBER] @regex = @token.regex end it "should match against numeric terms" do @regex.should =~ "2982383139" end it "should match against float terms" do @regex.should =~ "29823.235" end it "should match against hexadecimal terms" do @regex.should =~ "0xBEEF0023" end it "should match against float with exponent terms" do @regex.should =~ "10e23" end it "should match against float terms with negative exponents" do @regex.should =~ "10e-23" end it "should match against float terms with fractional parts and exponent" do @regex.should =~ "1.234e23" end it "should return the NAME token and the value" do @token.convert(stub("lexer"), "myval").should == [Puppet::Parser::Lexer::TOKENS[:NAME], "myval"] end end describe Puppet::Parser::Lexer::TOKENS[:COMMENT] do before { @token = Puppet::Parser::Lexer::TOKENS[:COMMENT] } it "should match against lines starting with '#'" do @token.regex.should =~ "# this is a comment" end it "should be marked to get skipped" do @token.skip?.should be_true end it "should be marked to accumulate" do @token.accumulate?.should be_true end it "'s block should return the comment without the #" do @token.convert(@lexer,"# this is a comment")[1].should == "this is a comment" end end describe Puppet::Parser::Lexer::TOKENS[:MLCOMMENT] do before do @token = Puppet::Parser::Lexer::TOKENS[:MLCOMMENT] @lexer = stub 'lexer', :line => 0 end it "should match against lines enclosed with '/*' and '*/'" do @token.regex.should =~ "/* this is a comment */" end it "should match multiple lines enclosed with '/*' and '*/'" do @token.regex.should =~ """/* this is a comment */""" end it "should increase the lexer current line number by the amount of lines spanned by the comment" do @lexer.expects(:line=).with(2) @token.convert(@lexer, "1\n2\n3") end it "should not greedily match comments" do match = @token.regex.match("/* first */ word /* second */") match[1].should == " first " end it "should be marked to accumulate" do @token.accumulate?.should be_true end it "'s block should return the comment without the comment marks" do @lexer.stubs(:line=).with(0) @token.convert(@lexer,"/* this is a comment */")[1].should == "this is a comment" end end describe Puppet::Parser::Lexer::TOKENS[:RETURN] do before { @token = Puppet::Parser::Lexer::TOKENS[:RETURN] } it "should match against carriage returns" do @token.regex.should =~ "\n" end it "should be marked to initiate text skipping" do @token.skip_text.should be_true end it "should be marked to increment the line" do @token.incr_line.should be_true end end def tokens_scanned_from(s) lexer = Puppet::Parser::Lexer.new lexer.string = s lexer.fullscan[0..-2] end describe Puppet::Parser::Lexer,"when lexing strings" do { %q{'single quoted string')} => [[:STRING,'single quoted string']], %q{"double quoted string"} => [[:STRING,'double quoted string']], %q{'single quoted string with an escaped "\\'"'} => [[:STRING,'single quoted string with an escaped "\'"']], %q{'single quoted string with an escaped "\$"'} => [[:STRING,'single quoted string with an escaped "\$"']], %q{'single quoted string with an escaped "\."'} => [[:STRING,'single quoted string with an escaped "\."']], %q{'single quoted string with an escaped "\n"'} => [[:STRING,'single quoted string with an escaped "\n"']], %q{'single quoted string with an escaped "\\\\"'} => [[:STRING,'single quoted string with an escaped "\\\\"']], %q{"string with an escaped '\\"'"} => [[:STRING,"string with an escaped '\"'"]], %q{"string with an escaped '\\$'"} => [[:STRING,"string with an escaped '$'"]], %q{"string with $v (but no braces)"} => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' (but no braces)']], %q["string with ${v} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'v'],[:DQPOST,' in braces']], %q["string with ${qualified::var} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,'qualified::var'],[:DQPOST,' in braces']], %q{"string with $v and $v (but no braces)"} => [[:DQPRE,"string with "],[:VARIABLE,"v"],[:DQMID," and "],[:VARIABLE,"v"],[:DQPOST," (but no braces)"]], %q["string with ${v} and ${v} in braces"] => [[:DQPRE,"string with "],[:VARIABLE,"v"],[:DQMID," and "],[:VARIABLE,"v"],[:DQPOST," in braces"]], %q["string with ${'a nested single quoted string'} inside it."] => [[:DQPRE,"string with "],[:STRING,'a nested single quoted string'],[:DQPOST,' inside it.']], %q["string with ${['an array ',$v2]} in it."] => [[:DQPRE,"string with "],:LBRACK,[:STRING,"an array "],:COMMA,[:VARIABLE,"v2"],:RBRACK,[:DQPOST," in it."]], %q{a simple "scanner" test} => [[:NAME,"a"],[:NAME,"simple"], [:STRING,"scanner"],[:NAME,"test"]], %q{a simple 'single quote scanner' test} => [[:NAME,"a"],[:NAME,"simple"], [:STRING,"single quote scanner"],[:NAME,"test"]], %q{a harder 'a $b \c"'} => [[:NAME,"a"],[:NAME,"harder"], [:STRING,'a $b \c"']], %q{a harder "scanner test"} => [[:NAME,"a"],[:NAME,"harder"], [:STRING,"scanner test"]], %q{a hardest "scanner \"test\""} => [[:NAME,"a"],[:NAME,"hardest"],[:STRING,'scanner "test"']], %Q{a hardestest "scanner \\"test\\"\n"} => [[:NAME,"a"],[:NAME,"hardestest"],[:STRING,%Q{scanner "test"\n}]], %q{function("call")} => [[:NAME,"function"],[:LPAREN,"("],[:STRING,'call'],[:RPAREN,")"]], %q["string with ${(3+5)/4} nested math."] => [[:DQPRE,"string with "],:LPAREN,[:NAME,"3"],:PLUS,[:NAME,"5"],:RPAREN,:DIV,[:NAME,"4"],[:DQPOST," nested math."]], %q["$$$$"] => [[:STRING,"$$$$"]], %q["$variable"] => [[:DQPRE,""],[:VARIABLE,"variable"],[:DQPOST,""]], %q["$var$other"] => [[:DQPRE,""],[:VARIABLE,"var"],[:DQMID,""],[:VARIABLE,"other"],[:DQPOST,""]], %q["foo$bar$"] => [[:DQPRE,"foo"],[:VARIABLE,"bar"],[:DQPOST,"$"]], %q["foo$$bar"] => [[:DQPRE,"foo$"],[:VARIABLE,"bar"],[:DQPOST,""]], %q[""] => [[:STRING,""]], }.each { |src,expected_result| it "should handle #{src} correctly" do tokens_scanned_from(src).should be_like(*expected_result) end } end describe Puppet::Parser::Lexer::TOKENS[:DOLLAR_VAR] do before { @token = Puppet::Parser::Lexer::TOKENS[:DOLLAR_VAR] } it "should match against alpha words prefixed with '$'" do @token.regex.should =~ '$this_var' end it "should return the VARIABLE token and the variable name stripped of the '$'" do @token.convert(stub("lexer"), "$myval").should == [Puppet::Parser::Lexer::TOKENS[:VARIABLE], "myval"] end end describe Puppet::Parser::Lexer::TOKENS[:REGEX] do before { @token = Puppet::Parser::Lexer::TOKENS[:REGEX] } it "should match against any expression enclosed in //" do @token.regex.should =~ '/this is a regex/' end it 'should not match if there is \n in the regex' do @token.regex.should_not =~ "/this is \n a regex/" end describe "when scanning" do it "should not consider escaped slashes to be the end of a regex" do tokens_scanned_from("$x =~ /this \\/ foo/").should be_like(__,__,[:REGEX,%r{this / foo}]) end it "should not lex chained division as a regex" do tokens_scanned_from("$x = $a/$b/$c").collect { |name, data| name }.should_not be_include( :REGEX ) end it "should accept a regular expression after NODE" do tokens_scanned_from("node /www.*\.mysite\.org/").should be_like(__,[:REGEX,Regexp.new("www.*\.mysite\.org")]) end it "should accept regular expressions in a CASE" do s = %q{case $variable { "something": {$othervar = 4096 / 2} /regex/: {notice("this notably sucks")} } } tokens_scanned_from(s).should be_like( :CASE,:VARIABLE,:LBRACE,:STRING,:COLON,:LBRACE,:VARIABLE,:EQUALS,:NAME,:DIV,:NAME,:RBRACE,[:REGEX,/regex/],:COLON,:LBRACE,:NAME,:LPAREN,:STRING,:RPAREN,:RBRACE,:RBRACE ) end end it "should return the REGEX token and a Regexp" do @token.convert(stub("lexer"), "/myregex/").should == [Puppet::Parser::Lexer::TOKENS[:REGEX], Regexp.new(/myregex/)] end end describe Puppet::Parser::Lexer, "when lexing comments" do before { @lexer = Puppet::Parser::Lexer.new } it "should accumulate token in munge_token" do token = stub 'token', :skip => true, :accumulate? => true, :incr_line => nil, :skip_text => false token.stubs(:convert).with(@lexer, "# this is a comment").returns([token, " this is a comment"]) @lexer.munge_token(token, "# this is a comment") @lexer.munge_token(token, "# this is a comment") @lexer.getcomment.should == " this is a comment\n this is a comment\n" end it "should add a new comment stack level on LBRACE" do @lexer.string = "{" @lexer.expects(:commentpush) @lexer.fullscan end it "should return the current comments on getcomment" do @lexer.string = "# comment" @lexer.fullscan @lexer.getcomment.should == "comment\n" end it "should discard the previous comments on blank line" do @lexer.string = "# 1\n\n# 2" @lexer.fullscan @lexer.getcomment.should == "2\n" end it "should skip whitespace before lexing the next token after a non-token" do tokens_scanned_from("/* 1\n\n */ \ntest").should be_like([:NAME, "test"]) end it "should not return comments seen after the current line" do @lexer.string = "# 1\n\n# 2" @lexer.fullscan @lexer.getcomment(1).should == "" end it "should return a comment seen before the current line" do @lexer.string = "# 1\n# 2" @lexer.fullscan @lexer.getcomment(2).should == "1\n2\n" end end # FIXME: We need to rewrite all of these tests, but I just don't want to take the time right now. describe "Puppet::Parser::Lexer in the old tests" do before { @lexer = Puppet::Parser::Lexer.new } it "should do simple lexing" do { %q{\\} => [[:BACKSLASH,"\\"]], %q{simplest scanner test} => [[:NAME,"simplest"],[:NAME,"scanner"],[:NAME,"test"]], %Q{returned scanner test\n} => [[:NAME,"returned"],[:NAME,"scanner"],[:NAME,"test"]] }.each { |source,expected| tokens_scanned_from(source).should be_like(*expected) } end it "should fail usefully" do lambda { tokens_scanned_from('^') }.should raise_error(RuntimeError) end it "should fail if the string is not set" do lambda { @lexer.fullscan }.should raise_error(Puppet::LexError) end it "should correctly identify keywords" do tokens_scanned_from("case").should be_like([:CASE, "case"]) end it "should correctly parse class references" do %w{Many Different Words A Word}.each { |t| tokens_scanned_from(t).should be_like([:CLASSREF,t])} end # #774 it "should correctly parse namespaced class refernces token" do %w{Foo ::Foo Foo::Bar ::Foo::Bar}.each { |t| tokens_scanned_from(t).should be_like([:CLASSREF, t]) } end it "should correctly parse names" do %w{this is a bunch of names}.each { |t| tokens_scanned_from(t).should be_like([:NAME,t]) } end it "should correctly parse names with numerals" do %w{1name name1 11names names11}.each { |t| tokens_scanned_from(t).should be_like([:NAME,t]) } end it "should correctly parse empty strings" do lambda { tokens_scanned_from('$var = ""') }.should_not raise_error end it "should correctly parse virtual resources" do tokens_scanned_from("@type {").should be_like([:AT, "@"], [:NAME, "type"], [:LBRACE, "{"]) end it "should correctly deal with namespaces" do @lexer.string = %{class myclass} @lexer.fullscan @lexer.namespace.should == "myclass" @lexer.namepop @lexer.namespace.should == "" @lexer.string = "class base { class sub { class more" @lexer.fullscan @lexer.namespace.should == "base::sub::more" @lexer.namepop @lexer.namespace.should == "base::sub" end it "should not put class instantiation on the namespace" do @lexer.string = "class base { class sub { class { mode" @lexer.fullscan @lexer.namespace.should == "base::sub" end it "should correctly handle fully qualified names" do @lexer.string = "class base { class sub::more {" @lexer.fullscan @lexer.namespace.should == "base::sub::more" @lexer.namepop @lexer.namespace.should == "base" end it "should correctly lex variables" do ["$variable", "$::variable", "$qualified::variable", "$further::qualified::variable"].each do |string| tokens_scanned_from(string).should be_like([:VARIABLE,string.sub(/^\$/,'')]) end end end require 'puppettest/support/utils' describe "Puppet::Parser::Lexer in the old tests when lexing example files" do - extend PuppetTest extend PuppetTest::Support::Utils textfiles do |file| it "should correctly lex #{file}" do lexer = Puppet::Parser::Lexer.new lexer.file = file lambda { lexer.fullscan }.should_not raise_error end end end diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb index 059d010bb..648527924 100755 --- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb @@ -1,228 +1,230 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet_spec/files' -require 'puppettest' require 'puppettest/support/utils' require 'puppettest/fileparsing' +require 'tmpdir' +require 'puppettest/fakes' provider_class = Puppet::Type.type(:ssh_authorized_key).provider(:parsed) describe provider_class do include PuppetSpec::Files + extend PuppetTest::Support::Utils include PuppetTest include PuppetTest::FileParsing before :each do @sshauthkey_class = Puppet::Type.type(:ssh_authorized_key) @provider = @sshauthkey_class.provider(:parsed) @keyfile = File.join(Dir.tmpdir, 'authorized_keys') @provider.any_instance.stubs(:target).returns @keyfile @user = 'random_bob' Puppet::Util.stubs(:uid).with(@user).returns 12345 end after :each do @provider.initvars end def mkkey(args) fakeresource = fakeresource(:ssh_authorized_key, args[:name]) fakeresource.stubs(:should).with(:user).returns @user fakeresource.stubs(:should).with(:target).returns @keyfile key = @provider.new(fakeresource) args.each do |p,v| key.send(p.to_s + "=", v) end key end def genkey(key) @provider.stubs(:filetype).returns(Puppet::Util::FileType::FileTypeRam) File.stubs(:chown) File.stubs(:chmod) Puppet::Util::SUIDManager.stubs(:asuser).yields key.flush @provider.target_object(@keyfile).read end - PuppetTest.fakedata("data/providers/ssh_authorized_key/parsed").each { |file| + fakedata("data/providers/ssh_authorized_key/parsed").each { |file| it "should be able to parse example data in #{file}" do fakedataparse(file) end } it "should be able to generate a basic authorized_keys file" do key = mkkey( { :name => "Just Testing", :key => "AAAAfsfddsjldjgksdflgkjsfdlgkj", :type => "ssh-dss", :ensure => :present, :options => [:absent] }) genkey(key).should == "ssh-dss AAAAfsfddsjldjgksdflgkjsfdlgkj Just Testing\n" end it "should be able to generate a authorized_keys file with options" do key = mkkey( { :name => "root@localhost", :key => "AAAAfsfddsjldjgksdflgkjsfdlgkj", :type => "ssh-rsa", :ensure => :present, :options => ['from="192.168.1.1"', "no-pty", "no-X11-forwarding"] }) genkey(key).should == "from=\"192.168.1.1\",no-pty,no-X11-forwarding ssh-rsa AAAAfsfddsjldjgksdflgkjsfdlgkj root@localhost\n" end it "should be able to parse options containing commas via its parse_options method" do options = %w{from="host1.reductlivelabs.com,host.reductivelabs.com" command="/usr/local/bin/run" ssh-pty} optionstr = options.join(", ") @provider.parse_options(optionstr).should == options end it "should use '' as name for entries that lack a comment" do line = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAut8aOSxenjOqF527dlsdHWV4MNoAsX14l9M297+SQXaQ5Z3BedIxZaoQthkDALlV/25A1COELrg9J2MqJNQc8Xe9XQOIkBQWWinUlD/BXwoOTWEy8C8zSZPHZ3getMMNhGTBO+q/O+qiJx3y5cA4MTbw2zSxukfWC87qWwcZ64UUlegIM056vPsdZWFclS9hsROVEa57YUMrehQ1EGxT4Z5j6zIopufGFiAPjZigq/vqgcAqhAKP6yu4/gwO6S9tatBeEjZ8fafvj1pmvvIplZeMr96gHE7xS3pEEQqnB3nd4RY7AF6j9kFixnsytAUO7STPh/M3pLiVQBN89TvWPQ==" @provider.parse(line)[0][:name].should == "" end end describe provider_class do before :each do @resource = stub("resource", :name => "foo") @resource.stubs(:[]).returns "foo" @provider = provider_class.new(@resource) provider_class.stubs(:filetype).returns(Puppet::Util::FileType::FileTypeRam) Puppet::Util::SUIDManager.stubs(:asuser).yields end describe "when flushing" do before :each do # Stub file and directory operations Dir.stubs(:mkdir) File.stubs(:chmod) File.stubs(:chown) end describe "and both a user and a target have been specified" do before :each do Puppet::Util.stubs(:uid).with("random_bob").returns 12345 @resource.stubs(:should).with(:user).returns "random_bob" target = "/tmp/.ssh_dir/place_to_put_authorized_keys" @resource.stubs(:should).with(:target).returns target end it "should create the directory" do File.stubs(:exist?).with("/tmp/.ssh_dir").returns false Dir.expects(:mkdir).with("/tmp/.ssh_dir", 0700) @provider.flush end it "should chown the directory to the user" do uid = Puppet::Util.uid("random_bob") File.expects(:chown).with(uid, nil, "/tmp/.ssh_dir") @provider.flush end it "should chown the key file to the user" do uid = Puppet::Util.uid("random_bob") File.expects(:chown).with(uid, nil, "/tmp/.ssh_dir/place_to_put_authorized_keys") @provider.flush end it "should chmod the key file to 0600" do File.expects(:chmod).with(0600, "/tmp/.ssh_dir/place_to_put_authorized_keys") @provider.flush end end describe "and a user has been specified with no target" do before :each do @resource.stubs(:should).with(:user).returns "nobody" @resource.stubs(:should).with(:target).returns nil # # I'd like to use random_bob here and something like # # File.stubs(:expand_path).with("~random_bob/.ssh").returns "/users/r/random_bob/.ssh" # # but mocha objects strenuously to stubbing File.expand_path # so I'm left with using nobody. @dir = File.expand_path("~nobody/.ssh") end it "should create the directory if it doesn't exist" do File.stubs(:exist?).with(@dir).returns false Dir.expects(:mkdir).with(@dir,0700) @provider.flush end it "should not create or chown the directory if it already exist" do File.stubs(:exist?).with(@dir).returns false Dir.expects(:mkdir).never @provider.flush end it "should chown the directory to the user if it creates it" do File.stubs(:exist?).with(@dir).returns false Dir.stubs(:mkdir).with(@dir,0700) uid = Puppet::Util.uid("nobody") File.expects(:chown).with(uid, nil, @dir) @provider.flush end it "should not create or chown the directory if it already exist" do File.stubs(:exist?).with(@dir).returns false Dir.expects(:mkdir).never File.expects(:chown).never @provider.flush end it "should chown the key file to the user" do uid = Puppet::Util.uid("nobody") File.expects(:chown).with(uid, nil, File.expand_path("~nobody/.ssh/authorized_keys")) @provider.flush end it "should chmod the key file to 0600" do File.expects(:chmod).with(0600, File.expand_path("~nobody/.ssh/authorized_keys")) @provider.flush end end describe "and a target has been specified with no user" do before :each do @resource.stubs(:should).with(:user).returns nil @resource.stubs(:should).with(:target).returns("/tmp/.ssh_dir/place_to_put_authorized_keys") end it "should raise an error" do proc { @provider.flush }.should raise_error end end describe "and a invalid user has been specified with no target" do before :each do @resource.stubs(:should).with(:user).returns "thisusershouldnotexist" @resource.stubs(:should).with(:target).returns nil end it "should catch an exception and raise a Puppet error" do lambda { @provider.flush }.should raise_error(Puppet::Error) end end end end diff --git a/spec/unit/reports/tagmail_spec.rb b/spec/unit/reports/tagmail_spec.rb index 4349e999d..59cb5b2b8 100755 --- a/spec/unit/reports/tagmail_spec.rb +++ b/spec/unit/reports/tagmail_spec.rb @@ -1,94 +1,94 @@ #!/usr/bin/env ruby Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } require 'puppet/reports' -require 'puppettest' +require 'puppettest/support/utils' tagmail = Puppet::Reports.report(:tagmail) describe tagmail do - extend PuppetTest + extend PuppetTest::Support::Utils before do @processor = Puppet::Transaction::Report.new @processor.extend(Puppet::Reports.report(:tagmail)) end passers = File.join(datadir, "reports", "tagmail_passers.conf") File.readlines(passers).each do |line| it "should be able to parse '#{line.inspect}'" do @processor.parse(line) end end failers = File.join(datadir, "reports", "tagmail_failers.conf") File.readlines(failers).each do |line| it "should not be able to parse '#{line.inspect}'" do lambda { @processor.parse(line) }.should raise_error(ArgumentError) end end { "tag: abuse@domain.com" => [%w{abuse@domain.com}, %w{tag}, []], "tag, other: abuse@domain.com" => [%w{abuse@domain.com}, %w{tag other}, []], "tag-other: abuse@domain.com" => [%w{abuse@domain.com}, %w{tag-other}, []], "tag, !other: abuse@domain.com" => [%w{abuse@domain.com}, %w{tag}, %w{other}], "tag, !other, one, !two: abuse@domain.com" => [%w{abuse@domain.com}, %w{tag one}, %w{other two}], "tag: abuse@domain.com, other@domain.com" => [%w{abuse@domain.com other@domain.com}, %w{tag}, []] }.each do |line, results| it "should parse '#{line}' as #{results.inspect}" do @processor.parse(line).shift.should == results end end describe "when matching logs" do before do @processor << Puppet::Util::Log.new(:level => :notice, :message => "first", :tags => %w{one}) @processor << Puppet::Util::Log.new(:level => :notice, :message => "second", :tags => %w{one two}) @processor << Puppet::Util::Log.new(:level => :notice, :message => "third", :tags => %w{one two three}) end def match(pos = [], neg = []) pos = Array(pos) neg = Array(neg) result = @processor.match([[%w{abuse@domain.com}, pos, neg]]) actual_result = result.shift if actual_result actual_result[1] else nil end end it "should match all messages when provided the 'all' tag as a positive matcher" do results = match("all") %w{first second third}.each do |str| results.should be_include(str) end end it "should remove messages that match a negated tag" do match("all", "three").should_not be_include("third") end it "should find any messages tagged with a provided tag" do results = match("two") results.should be_include("second") results.should be_include("third") results.should_not be_include("first") end it "should allow negation of specific tags from a specific tag list" do results = match("two", "three") results.should be_include("second") results.should_not be_include("third") end it "should allow a tag to negate all matches" do results = match([], "one") results.should be_nil end end end diff --git a/spec/unit/util/backups_spec.rb b/spec/unit/util/backups_spec.rb index 5c10d4c3c..259b18652 100755 --- a/spec/unit/util/backups_spec.rb +++ b/spec/unit/util/backups_spec.rb @@ -1,159 +1,158 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/util/backups' -include PuppetTest describe Puppet::Util::Backups do before do FileTest.stubs(:exists?).returns true end describe "when backing up a file" do it "should noop if the file does not exist" do FileTest.expects(:exists?).returns false file = Puppet::Type.type(:file).new(:name => '/no/such/file') file.expects(:bucket).never file.perform_backup end it "should succeed silently if self[:backup] is false" do file = Puppet::Type.type(:file).new(:name => '/no/such/file', :backup => false) file.expects(:bucket).never FileTest.expects(:exists?).never file.perform_backup end it "a bucket should be used when provided" do path = '/my/file' File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') bucket = stub('bucket', 'name' => 'foo') file.stubs(:bucket).returns bucket bucket.expects(:backup).with(path).returns("mysum") file.perform_backup end it "should propagate any exceptions encountered when backing up to a filebucket" do path = '/my/file' File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') bucket = stub('bucket', 'name' => 'foo') file.stubs(:bucket).returns bucket bucket.expects(:backup).raises ArgumentError lambda { file.perform_backup }.should raise_error(ArgumentError) end describe "and no filebucket is configured" do it "should remove any local backup if one exists" do path = '/my/file' FileTest.stubs(:exists?).returns true backup = path + ".foo" File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file") File.expects(:unlink).with(backup) FileUtils.stubs(:cp_r) file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup end it "should fail when the old backup can't be removed" do path = '/my/file' FileTest.stubs(:exists?).returns true backup = path + ".foo" File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file") File.expects(:unlink).raises ArgumentError FileUtils.expects(:cp_r).never file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') lambda { file.perform_backup }.should raise_error(Puppet::Error) end it "should not try to remove backups that don't exist" do path = '/my/file' FileTest.stubs(:exists?).returns true backup = path + ".foo" File.expects(:lstat).with(backup).raises(Errno::ENOENT) File.expects(:unlink).never FileUtils.stubs(:cp_r) file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup end it "a copy should be created in the local directory" do path = '/my/file' FileTest.stubs(:exists?).with(path).returns true FileUtils.expects(:cp_r).with(path, path + ".foo", :preserve => true) file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') file.perform_backup.should be_true end it "should propagate exceptions if no backup can be created" do path = '/my/file' FileTest.stubs(:exists?).with(path).returns true FileUtils.expects(:cp_r).raises ArgumentError file = Puppet::Type.type(:file).new(:name => path, :backup => '.foo') lambda { file.perform_backup }.should raise_error(Puppet::Error) end end end describe "when backing up a directory" do it "a bucket should work when provided" do path = '/my/dir' File.stubs(:file?).returns true Find.expects(:find).with(path).yields("/my/dir/file") bucket = stub('bucket', :name => "eh") bucket.expects(:backup).with("/my/dir/file").returns true file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') file.stubs(:bucket).returns bucket File.stubs(:stat).with(path).returns(stub('stat', :ftype => 'directory')) file.perform_backup end it "should do nothing when recursing" do path = '/my/dir' bucket = stub('bucket', :name => "eh") bucket.expects(:backup).never file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo', :recurse => true) file.stubs(:bucket).returns bucket File.stubs(:stat).with(path).returns(stub('stat', :ftype => 'directory')) Find.expects(:find).never file.perform_backup end end end diff --git a/test/lib/mocha_standalone.rb b/test/lib/mocha_standalone.rb deleted file mode 100644 index ce605811a..000000000 --- a/test/lib/mocha_standalone.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'mocha/standalone' -require 'mocha/object' diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb index 294d0ef8d..0b3a89a72 100755 --- a/test/lib/puppettest.rb +++ b/test/lib/puppettest.rb @@ -1,339 +1,319 @@ # Add .../test/lib testlib = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift(testlib) unless $LOAD_PATH.include?(testlib) # Add .../lib mainlib = File.expand_path(File.join(File.dirname(__FILE__), '../../lib')) $LOAD_PATH.unshift(mainlib) unless $LOAD_PATH.include?(mainlib) require 'puppet' - -# include any gems in vendor/gems -Dir["#{mainlib}/../vendor/gems/**"].each do |path| - libpath = File.join(path, "lib") - if File.directory?(libpath) - $LOAD_PATH.unshift(libpath) - else - $LOAD_PATH.unshift(path) - end -end - require 'mocha' # Only load the test/unit class if we're not in the spec directory. # Else we get the bogus 'no tests, no failures' message. unless Dir.getwd =~ /spec/ require 'test/unit' end # Yay; hackish but it works if ARGV.include?("-d") ARGV.delete("-d") $console = true 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 +require File.expand_path(File.join(File.dirname(__FILE__), '../../spec/monkey_patches/publicize_methods')) module PuppetTest # These need to be here for when rspec tests use these # support methods. @@tmpfiles = [] # Munge cli arguments, so we can enable debugging if we want # and so we can run just specific methods. def self.munge_argv require 'getoptlong' result = GetoptLong.new( [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--resolve", "-r", GetoptLong::REQUIRED_ARGUMENT ], [ "-n", GetoptLong::REQUIRED_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ] ) usage = "USAGE: TESTOPTS='[-n -n ...] [-d]' rake [target] [target] ..." opts = [] dir = method = nil result.each { |opt,arg| case opt when "--resolve" dir, method = arg.split(",") when "--debug" $puppet_debug = true Puppet::Util::Log.level = :debug Puppet::Util::Log.newdestination(:console) when "--help" puts usage exit else opts << opt << arg end } suites = nil args = ARGV.dup # Reset the options, so the test suite can deal with them (this is # what makes things like '-n' work). opts.each { |o| ARGV << o } args end # Find the root of the Puppet tree; this is not the test directory, but # the parent of that dir. def basedir(*list) unless defined?(@@basedir) Dir.chdir(File.dirname(__FILE__)) do @@basedir = File.dirname(File.dirname(Dir.getwd)) end end if list.empty? @@basedir else File.join(@@basedir, *list) end end def datadir(*list) File.join(basedir, "test", "data", *list) end def exampledir(*args) @@exampledir = File.join(basedir, "examples") unless defined?(@@exampledir) if args.empty? return @@exampledir else return File.join(@@exampledir, *args) end end module_function :basedir, :datadir, :exampledir def cleanup(&block) @@cleaners << block end # Rails clobbers RUBYLIB, thanks def libsetup curlibs = ENV["RUBYLIB"].split(":") $LOAD_PATH.reject do |dir| dir =~ /^\/usr/ end.each do |dir| curlibs << dir unless curlibs.include?(dir) end ENV["RUBYLIB"] = curlibs.join(":") end def logcollector collector = [] Puppet::Util::Log.newdestination(collector) cleanup do Puppet::Util::Log.close(collector) end collector end def rake? $0 =~ /test_loader/ end # Redirect stdout and stderr def redirect @stderr = tempfile @stdout = tempfile $stderr = File.open(@stderr, "w") $stdout = File.open(@stdout, "w") cleanup do $stderr = STDERR $stdout = STDOUT end end def setup ENV["PATH"] += File::PATH_SEPARATOR + "/usr/sbin" unless ENV["PATH"].split(File::PATH_SEPARATOR).include?("/usr/sbin") @memoryatstart = Puppet::Util.memory if defined?(@@testcount) @@testcount += 1 else @@testcount = 0 end @configpath = File.join( tmpdir, "configdir" + @@testcount.to_s + "/" ) unless defined? $user and $group $user = nonrootuser.uid.to_s $group = nonrootgroup.gid.to_s end Puppet.settings.clear Puppet[:user] = $user Puppet[:group] = $group Puppet[:confdir] = @configpath Puppet[:vardir] = @configpath Dir.mkdir(@configpath) unless File.exists?(@configpath) @@tmpfiles << @configpath << tmpdir @@tmppids = [] @@cleaners = [] @logs = [] # If we're running under rake, then disable debugging and such. #if rake? or ! Puppet[:debug] #if defined?($puppet_debug) or ! rake? Puppet[:color] = false if textmate? Puppet::Util::Log.newdestination(@logs) if defined? $console Puppet.info @method_name Puppet::Util::Log.newdestination(:console) Puppet[:trace] = true end Puppet::Util::Log.level = :debug #$VERBOSE = 1 #else # Puppet::Util::Log.close # Puppet::Util::Log.newdestination(@logs) # Puppet[:httplog] = tempfile #end Puppet[:ignoreschedules] = true #@start = Time.now #Facter.stubs(:value).returns "stubbed_value" #Facter.stubs(:to_hash).returns({}) end def tempfile(suffix = '') if defined?(@@tmpfilenum) @@tmpfilenum += 1 else @@tmpfilenum = 1 end f = File.join(self.tmpdir, "tempfile_" + @@tmpfilenum.to_s + suffix) @@tmpfiles ||= [] @@tmpfiles << f f end def textmate? !!ENV["TM_FILENAME"] end def tstdir dir = tempfile Dir.mkdir(dir) dir end def tmpdir unless @tmpdir @tmpdir = case Facter["operatingsystem"].value when "Darwin"; "/private/tmp" when "SunOS"; "/var/tmp" else "/tmp" end @tmpdir = File.join(@tmpdir, "puppettesting#{Process.pid}") unless File.exists?(@tmpdir) FileUtils.mkdir_p(@tmpdir) File.chmod(01777, @tmpdir) end end @tmpdir end def remove_tmp_files @@tmpfiles.each { |file| unless file =~ /tmp/ puts "Not deleting tmpfile #{file}" next end if FileTest.exists?(file) system("chmod -R 755 #{file}") system("rm -rf #{file}") end } @@tmpfiles.clear end def teardown #@stop = Time.now #File.open("/tmp/test_times.log", ::File::WRONLY|::File::CREAT|::File::APPEND) { |f| f.puts "%0.4f %s %s" % [@stop - @start, @method_name, self.class] } @@cleaners.each { |cleaner| cleaner.call } remove_tmp_files @@tmppids.each { |pid| %x{kill -INT #{pid} 2>/dev/null} } @@tmppids.clear Puppet::Util::Storage.clear Puppet.clear Puppet.settings.clear Puppet::Util::Cacher.expire @memoryatend = Puppet::Util.memory diff = @memoryatend - @memoryatstart Puppet.info "#{self.class}##{@method_name} memory growth (#{@memoryatstart} to #{@memoryatend}): #{diff}" if diff > 1000 # reset all of the logs Puppet::Util::Log.close_all @logs.clear # Just in case there are processes waiting to die... require 'timeout' begin Timeout::timeout(5) do Process.waitall end rescue Timeout::Error # just move on end end def logstore @logs = [] Puppet::Util::Log.newdestination(@logs) end end require 'puppettest/support' require 'puppettest/filetesting' require 'puppettest/fakes' require 'puppettest/exetest' require 'puppettest/parsertesting' require 'puppettest/servertest' require 'puppettest/testcase' diff --git a/test/lib/puppettest/fakes.rb b/test/lib/puppettest/fakes.rb index aaa711004..712332b74 100644 --- a/test/lib/puppettest/fakes.rb +++ b/test/lib/puppettest/fakes.rb @@ -1,199 +1,199 @@ -require 'puppettest' +require File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/puppet/util')) module PuppetTest # A baseclass for the faketypes. class FakeModel include Puppet::Util class << self attr_accessor :name, :realresource @name = :fakeresource end def self.key_attributes @realresource.key_attributes end def self.validproperties Puppet::Type.type(@name).validproperties end def self.validproperty?(name) Puppet::Type.type(@name).validproperty?(name) end def self.to_s "Fake#{@name.to_s.capitalize}" end def [](param) if @realresource.attrtype(param) == :property @is[param] else @params[param] end end def []=(param, value) param = symbolize(param) raise Puppet::DevError, "Invalid attribute #{param} for #{@realresource.name}" unless @realresource.valid_parameter?(param) if @realresource.attrtype(param) == :property @should[param] = value else @params[param] = value end end def initialize(name) @realresource = Puppet::Type.type(self.class.name) raise "Could not find type #{self.class.name}" unless @realresource @is = {} @should = {} @params = {} self[@realresource.key_attributes.first] = name end def inspect "#{self.class.to_s.sub(/.+::/, '')}(#{super()})" end def is(param) @is[param] end def should(param) @should[param] end def to_hash hash = @params.dup [@is, @should].each do |h| h.each do |p, v| hash[p] = v end end hash end def name self[:name] end end class FakeProvider attr_accessor :resource class << self attr_accessor :name, :resource_type, :methods end # A very low number, so these never show up as defaults via the standard # algorithms. def self.defaultnum -50 end # Set up methods to fake things def self.apimethods(*ary) @resource_type.validproperties.each do |property| ary << property unless ary.include? property end attr_accessor(*ary) @methods = ary end def self.default? false end def self.initvars @calls = Hash.new do |hash, key| hash[key] = 0 end end def self.source self.name end def self.supports_parameter?(param) true end def self.suitable? true end def clear @resource = nil end def initialize(resource) @resource = resource end def properties self.class.resource_type.validproperties.inject({}) do |props, name| props[name] = self.send(name) || :absent props end end end class FakeParsedProvider < FakeProvider def hash ret = {} instance_variables.each do |v| v = v.sub("@", '') if val = self.send(v) ret[v.intern] = val end end ret end def store(hash) hash.each do |n, v| method = n.to_s + "=" send(method, v) if respond_to? method end end end @@fakeresources = {} @@fakeproviders = {} def fakeresource(type, name, options = {}) type = type.intern if type.is_a? String unless @@fakeresources.include? type @@fakeresources[type] = Class.new(FakeModel) @@fakeresources[type].name = type resource = Puppet::Type.type(type) raise("Could not find type #{type}") unless resource @@fakeresources[type].realresource = resource end obj = @@fakeresources[type].new(name) options.each do |name, val| obj[name] = val end obj end module_function :fakeresource def fakeprovider(type, resource) type = type.intern if type.is_a? String unless @@fakeproviders.include? type @@fakeproviders[type] = Class.new(FakeModel) do @name = type end end @@fakeproviders[type].new(resource) end module_function :fakeprovider end diff --git a/test/lib/puppettest/support/assertions.rb b/test/lib/puppettest/support/assertions.rb index 7f326b119..31fa3f1da 100644 --- a/test/lib/puppettest/support/assertions.rb +++ b/test/lib/puppettest/support/assertions.rb @@ -1,66 +1,64 @@ -require 'puppettest' require 'puppettest/support/utils' require 'fileutils' - module PuppetTest include PuppetTest::Support::Utils def assert_logged(level, regex, msg = nil) # Skip verifying logs that we're not supposed to send. return unless Puppet::Util::Log.sendlevel?(level) r = @logs.detect { |l| l.level == level and l.message =~ regex } @logs.clear assert(r, msg) end def assert_uid_gid(uid, gid, filename) flunk "Must be uid 0 to run these tests" unless Process.uid == 0 fork do Puppet::Util::SUIDManager.gid = gid Puppet::Util::SUIDManager.uid = uid # FIXME: use the tempfile method from puppettest.rb system("mkfifo #{filename}") f = File.open(filename, "w") f << "#{Puppet::Util::SUIDManager.uid}\n#{Puppet::Util::SUIDManager.gid}\n" yield if block_given? end # avoid a race. true while !File.exists? filename f = File.open(filename, "r") a = f.readlines assert_equal(uid, a[0].chomp.to_i, "UID was incorrect") assert_equal(gid, a[1].chomp.to_i, "GID was incorrect") FileUtils.rm(filename) end def assert_events(events, *resources) trans = nil comp = nil msg = nil raise Puppet::DevError, "Incorrect call of assert_events" unless events.is_a? Array msg = resources.pop if resources[-1].is_a? String config = resources2catalog(*resources) transaction = Puppet::Transaction.new(config) run_events(:evaluate, transaction, events, msg) transaction end # A simpler method that just applies what we have. def assert_apply(*resources) config = resources2catalog(*resources) events = nil assert_nothing_raised("Failed to evaluate") { events = config.apply.events } events end end diff --git a/test/lib/puppettest/support/utils.rb b/test/lib/puppettest/support/utils.rb index edc81d3d6..e022f123c 100644 --- a/test/lib/puppettest/support/utils.rb +++ b/test/lib/puppettest/support/utils.rb @@ -1,155 +1,160 @@ -require 'puppettest' - module PuppetTest::Support end module PuppetTest::Support::Utils def gcdebug(type) Puppet.warning "#{type}: #{ObjectSpace.each_object(type) { |o| }}" end + def basedir(*list) + unless defined? @@basedir + Dir.chdir(File.dirname(__FILE__)) do + @@basedir = File.dirname(File.dirname(File.dirname(File.dirname(Dir.getwd)))) + end + end + if list.empty? + @@basedir + else + File.join(@@basedir, *list) + end + end + + def fakedata(dir,pat='*') + glob = "#{basedir}/test/#{dir}/#{pat}" + files = Dir.glob(glob,File::FNM_PATHNAME) + raise Puppet::DevError, "No fakedata matching #{glob}" if files.empty? + files + end + + def datadir(*list) + File.join(basedir, "test", "data", *list) + end + # # TODO: I think this method needs to be renamed to something a little more # explanatory. # def newobj(type, name, hash) transport = Puppet::TransObject.new(name, "file") transport[:path] = path transport[:ensure] = "file" assert_nothing_raised { file = transport.to_ral } end # Turn a list of resources, or possibly a catalog and some resources, # into a catalog object. def resources2catalog(*resources) if resources[0].is_a?(Puppet::Resource::Catalog) config = resources.shift resources.each { |r| config.add_resource r } unless resources.empty? elsif resources[0].is_a?(Puppet::Type.type(:component)) raise ArgumentError, "resource2config() no longer accpts components" comp = resources.shift comp.delve else config = Puppet::Resource::Catalog.new resources.each { |res| config.add_resource res } end config end - # stop any services that might be hanging around - def stopservices - end - # TODO: rewrite this to use the 'etc' module. # Define a variable that contains the name of my user. def setme # retrieve the user name id = %x{id}.chomp if id =~ /uid=\d+\(([^\)]+)\)/ @me = $1 else puts id end raise "Could not retrieve user name; 'id' did not work" unless defined?(@me) end # Define a variable that contains a group I'm in. def set_mygroup # retrieve the user name group = %x{groups}.chomp.split(/ /)[0] raise "Could not find group to set in @mygroup" unless group @mygroup = group end def run_events(type, trans, events, msg) case type when :evaluate, :rollback # things are hunky-dory else raise Puppet::DevError, "Incorrect run_events type" end method = type trans.send(method) newevents = trans.events.reject { |e| e.status == 'failure' }.collect { |e| e.name } assert_equal(events, newevents, "Incorrect #{type} #{msg} events") trans end def fakefile(name) - ary = [PuppetTest.basedir, "test"] + ary = [basedir, "test"] ary += name.split("/") file = File.join(ary) raise Puppet::DevError, "No fakedata file #{file}" unless FileTest.exists?(file) file end # wrap how to retrieve the masked mode def filemode(file) File.stat(file).mode & 007777 end def memory Puppet::Util.memory end # a list of files that we can parse for testing def textfiles textdir = datadir "snippets" Dir.entries(textdir).reject { |f| f =~ /^\./ or f =~ /fail/ }.each { |f| yield File.join(textdir, f) } end def failers textdir = datadir "failers" # only parse this one file now files = Dir.entries(textdir).reject { |file| file =~ %r{\.swp} }.reject { |file| file =~ %r{\.disabled} }.collect { |file| File.join(textdir,file) }.find_all { |file| FileTest.file?(file) }.sort.each { |file| Puppet.debug "Processing #{file}" yield file } end def mk_catalog(*resources) if resources[0].is_a?(String) name = resources.shift else name = :testing end config = Puppet::Resource::Catalog.new :testing do |conf| resources.each { |resource| conf.add_resource resource } end config end end - -module PuppetTest - include PuppetTest::Support::Utils - - def fakedata(dir,pat='*') - glob = "#{basedir}/test/#{dir}/#{pat}" - files = Dir.glob(glob,File::FNM_PATHNAME) - raise Puppet::DevError, "No fakedata matching #{glob}" if files.empty? - files - end - module_function :fakedata - -end