diff options
| author | Stig Sandbeck Mathisen <ssm@debian.org> | 2013-02-05 10:44:00 +0100 |
|---|---|---|
| committer | Stig Sandbeck Mathisen <ssm@debian.org> | 2013-02-05 10:44:00 +0100 |
| commit | 107e8d1a41d447403883a6f6faa1cc40fb904720 (patch) | |
| tree | aaaeca9cb6289b3db94a105e6cb1b1270292337c /spec | |
| parent | 7a3cd3a80c8d57462509c7e193dfcc11fc61a191 (diff) | |
| parent | 480379d1f61d88e732bd10d6773845a788351ed3 (diff) | |
| download | puppet-upstream/3.1.0.tar.gz | |
Imported Upstream version 3.1.0upstream/3.1.0
Diffstat (limited to 'spec')
77 files changed, 1748 insertions, 860 deletions
diff --git a/spec/integration/application/apply_spec.rb b/spec/integration/application/apply_spec.rb index 233766e88..98de31d35 100755 --- a/spec/integration/application/apply_spec.rb +++ b/spec/integration/application/apply_spec.rb @@ -6,7 +6,7 @@ require 'puppet/application/apply' describe "apply" do include PuppetSpec::Files - describe "when applying provided catalogs", :if => Puppet.features.pson? do + describe "when applying provided catalogs" do it "should be able to apply catalogs provided in a file in pson" do file_to_create = tmpfile("pson_catalog") catalog = Puppet::Resource::Catalog.new diff --git a/spec/integration/defaults_spec.rb b/spec/integration/defaults_spec.rb index bdf857025..2764be1bb 100755 --- a/spec/integration/defaults_spec.rb +++ b/spec/integration/defaults_spec.rb @@ -87,6 +87,7 @@ describe "Puppet defaults" do it "should use the service user and group for the yamldir" do Puppet.settings.stubs(:service_user_available?).returns true + Puppet.settings.stubs(:service_group_available?).returns true Puppet.settings.setting(:yamldir).owner.should == Puppet.settings[:user] Puppet.settings.setting(:yamldir).group.should == Puppet.settings[:group] end diff --git a/spec/integration/indirector/catalog/queue_spec.rb b/spec/integration/indirector/catalog/queue_spec.rb index 31f5c1e49..f0f75263a 100755 --- a/spec/integration/indirector/catalog/queue_spec.rb +++ b/spec/integration/indirector/catalog/queue_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'puppet/resource/catalog' -describe "Puppet::Resource::Catalog::Queue", :if => Puppet.features.pson? do +describe "Puppet::Resource::Catalog::Queue" do before do Puppet::Resource::Catalog.indirection.terminus(:queue) @catalog = Puppet::Resource::Catalog.new diff --git a/spec/integration/network/formats_spec.rb b/spec/integration/network/formats_spec.rb index 5a328a3cb..2834e33f0 100755 --- a/spec/integration/network/formats_spec.rb +++ b/spec/integration/network/formats_spec.rb @@ -45,60 +45,47 @@ describe Puppet::Network::FormatHandler.format(:s) do end describe Puppet::Network::FormatHandler.format(:pson) do - describe "when pson is absent", :if => (! Puppet.features.pson?) do - - before do - @pson = Puppet::Network::FormatHandler.format(:pson) - end - - it "should not be suitable" do - @pson.should_not be_suitable - end + before do + @pson = Puppet::Network::FormatHandler.format(:pson) end - describe "when pson is available", :if => Puppet.features.pson? do - before do - @pson = Puppet::Network::FormatHandler.format(:pson) - end - - it "should be able to render an instance to pson" do - instance = PsonIntTest.new("foo") - PsonIntTest.canonical_order(@pson.render(instance)).should == PsonIntTest.canonical_order('{"type":"PsonIntTest","data":["foo"]}' ) - end + it "should be able to render an instance to pson" do + instance = PsonIntTest.new("foo") + PsonIntTest.canonical_order(@pson.render(instance)).should == PsonIntTest.canonical_order('{"type":"PsonIntTest","data":["foo"]}' ) + end - it "should be able to render arrays to pson" do - @pson.render([1,2]).should == '[1,2]' - end + it "should be able to render arrays to pson" do + @pson.render([1,2]).should == '[1,2]' + end - it "should be able to render arrays containing hashes to pson" do - @pson.render([{"one"=>1},{"two"=>2}]).should == '[{"one":1},{"two":2}]' - end + it "should be able to render arrays containing hashes to pson" do + @pson.render([{"one"=>1},{"two"=>2}]).should == '[{"one":1},{"two":2}]' + end - it "should be able to render multiple instances to pson" do - one = PsonIntTest.new("one") - two = PsonIntTest.new("two") + it "should be able to render multiple instances to pson" do + one = PsonIntTest.new("one") + two = PsonIntTest.new("two") - PsonIntTest.canonical_order(@pson.render([one,two])).should == PsonIntTest.canonical_order('[{"type":"PsonIntTest","data":["one"]},{"type":"PsonIntTest","data":["two"]}]') - end + PsonIntTest.canonical_order(@pson.render([one,two])).should == PsonIntTest.canonical_order('[{"type":"PsonIntTest","data":["one"]},{"type":"PsonIntTest","data":["two"]}]') + end - it "should be able to intern pson into an instance" do - @pson.intern(PsonIntTest, '{"type":"PsonIntTest","data":["foo"]}').should == PsonIntTest.new("foo") - end + it "should be able to intern pson into an instance" do + @pson.intern(PsonIntTest, '{"type":"PsonIntTest","data":["foo"]}').should == PsonIntTest.new("foo") + end - it "should be able to intern pson with no class information into an instance" do - @pson.intern(PsonIntTest, '["foo"]').should == PsonIntTest.new("foo") - end + it "should be able to intern pson with no class information into an instance" do + @pson.intern(PsonIntTest, '["foo"]').should == PsonIntTest.new("foo") + end - it "should be able to intern multiple instances from pson" do - @pson.intern_multiple(PsonIntTest, '[{"type": "PsonIntTest", "data": ["one"]},{"type": "PsonIntTest", "data": ["two"]}]').should == [ - PsonIntTest.new("one"), PsonIntTest.new("two") - ] - end + it "should be able to intern multiple instances from pson" do + @pson.intern_multiple(PsonIntTest, '[{"type": "PsonIntTest", "data": ["one"]},{"type": "PsonIntTest", "data": ["two"]}]').should == [ + PsonIntTest.new("one"), PsonIntTest.new("two") + ] + end - it "should be able to intern multiple instances from pson with no class information" do - @pson.intern_multiple(PsonIntTest, '[["one"],["two"]]').should == [ - PsonIntTest.new("one"), PsonIntTest.new("two") - ] - end + it "should be able to intern multiple instances from pson with no class information" do + @pson.intern_multiple(PsonIntTest, '[["one"],["two"]]').should == [ + PsonIntTest.new("one"), PsonIntTest.new("two") + ] end end diff --git a/spec/integration/parser/collector_spec.rb b/spec/integration/parser/collector_spec.rb index 27503ba5d..cb210b372 100755 --- a/spec/integration/parser/collector_spec.rb +++ b/spec/integration/parser/collector_spec.rb @@ -1,37 +1,117 @@ #! /usr/bin/env ruby require 'spec_helper' +require 'puppet_spec/compiler' require 'puppet/parser/collector' describe Puppet::Parser::Collector do - before do - @scope = Puppet::Parser::Scope.new(Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))) + include PuppetSpec::Compiler - @resource = Puppet::Parser::Resource.new("file", "/tmp/testing", :scope => @scope, :source => "fakesource") - {:owner => "root", :group => "bin", :mode => "644"}.each do |param, value| - @resource[param] = value - end + def expect_the_message_to_be(expected_messages, code, node = Puppet::Node.new('the node')) + catalog = compile_to_catalog(code, node) + messages = catalog.resources.find_all { |resource| resource.type == 'Notify' }. + collect { |notify| notify[:message] } + messages.should include(*expected_messages) + end + + it "matches on title" do + expect_the_message_to_be(["the message"], <<-MANIFEST) + @notify { "testing": message => "the message" } + + Notify <| title == "testing" |> + MANIFEST end - def query(text) - code = "File <| #{text} |>" - parser = Puppet::Parser::Parser.new(@scope.compiler) - return parser.parse(code).code[0].query - end - - {true => [%{title == "/tmp/testing"}, %{(title == "/tmp/testing")}, %{group == bin}, - %{title == "/tmp/testing" and group == bin}, %{title == bin or group == bin}, - %{title == "/tmp/testing" or title == bin}, %{title == "/tmp/testing"}, - %{(title == "/tmp/testing" or title == bin) and group == bin}], - false => [%{title == bin}, %{title == bin or (title == bin and group == bin)}, - %{title != "/tmp/testing"}, %{title != "/tmp/testing" and group != bin}] - }.each do |result, ary| - ary.each do |string| - it "should return '#{result}' when collecting resources with '#{string}'" do - str, code = query(string).evaluate @scope - code.should be_instance_of(Proc) - code.call(@resource).should == result - end + it "matches on other parameters" do + expect_the_message_to_be(["the message"], <<-MANIFEST) + @notify { "testing": message => "the message" } + @notify { "other testing": message => "the wrong message" } + + Notify <| message == "the message" |> + MANIFEST + end + + it "allows criteria to be combined with 'and'" do + expect_the_message_to_be(["the message"], <<-MANIFEST) + @notify { "testing": message => "the message" } + @notify { "other": message => "the message" } + + Notify <| title == "testing" and message == "the message" |> + MANIFEST + end + + it "allows criteria to be combined with 'or'" do + expect_the_message_to_be(["the message", "other message"], <<-MANIFEST) + @notify { "testing": message => "the message" } + @notify { "other": message => "other message" } + @notify { "yet another": message => "different message" } + + Notify <| title == "testing" or message == "other message" |> + MANIFEST + end + + it "allows criteria to be combined with 'or'" do + expect_the_message_to_be(["the message", "other message"], <<-MANIFEST) + @notify { "testing": message => "the message" } + @notify { "other": message => "other message" } + @notify { "yet another": message => "different message" } + + Notify <| title == "testing" or message == "other message" |> + MANIFEST + end + + it "allows criteria to be grouped with parens" do + expect_the_message_to_be(["the message", "different message"], <<-MANIFEST) + @notify { "testing": message => "different message", withpath => true } + @notify { "other": message => "the message" } + @notify { "yet another": message => "the message", withpath => true } + + Notify <| (title == "testing" or message == "the message") and withpath == true |> + MANIFEST + end + + it "does not do anything if nothing matches" do + expect_the_message_to_be([], <<-MANIFEST) + @notify { "testing": message => "different message" } + + Notify <| title == "does not exist" |> + MANIFEST + end + + it "excludes items with inequalities" do + expect_the_message_to_be(["good message"], <<-MANIFEST) + @notify { "testing": message => "good message" } + @notify { "the wrong one": message => "bad message" } + + Notify <| title != "the wrong one" |> + MANIFEST + end + + context "issue #10963" do + it "collects with override when inside a class" do + expect_the_message_to_be(["overridden message"], <<-MANIFEST) + @notify { "testing": message => "original message" } + + include collector_test + class collector_test { + Notify <| |> { + message => "overridden message" + } + } + MANIFEST + end + + it "collects with override when inside a define" do + expect_the_message_to_be(["overridden message"], <<-MANIFEST) + @notify { "testing": message => "original message" } + + collector_test { testing: } + define collector_test() { + Notify <| |> { + message => "overridden message" + } + } + MANIFEST end end end diff --git a/spec/integration/parser/ruby_manifest_spec.rb b/spec/integration/parser/ruby_manifest_spec.rb index e9cd819a7..75e9dd9be 100755 --- a/spec/integration/parser/ruby_manifest_spec.rb +++ b/spec/integration/parser/ruby_manifest_spec.rb @@ -13,6 +13,7 @@ describe "Pure ruby manifests" do @scope_resource = stub 'scope_resource', :builtin? => true, :finish => nil, :ref => 'Class[main]' @scope = stub 'scope', :resource => @scope_resource, :source => mock("source") @test_dir = tmpdir('ruby_manifest_test') + Puppet.expects(:deprecation_warning).at_least(1) end after do diff --git a/spec/integration/parser/scope_spec.rb b/spec/integration/parser/scope_spec.rb index 5bad1166e..66d29a438 100644 --- a/spec/integration/parser/scope_spec.rb +++ b/spec/integration/parser/scope_spec.rb @@ -4,7 +4,7 @@ require 'puppet_spec/compiler' describe "Two step scoping for variables" do include PuppetSpec::Compiler - def expect_the_message_to_be(message, node = Puppet::Node.new('the node')) + def expect_the_message_to_be(message, node = Puppet::Node.new('the node')) catalog = compile_to_catalog(yield, node) catalog.resource('Notify', 'something')[:message].should == message end @@ -13,6 +13,69 @@ describe "Two step scoping for variables" do Puppet.expects(:deprecation_warning).never end + describe "fully qualified variable names" do + it "keeps nodescope separate from topscope" do + expect_the_message_to_be('topscope') do <<-MANIFEST + $c = "topscope" + node default { + $c = "nodescope" + notify { 'something': message => $::c } + } + MANIFEST + end + end + end + + describe "when colliding class and variable names" do + it "finds a topscope variable with the same name as a class" do + expect_the_message_to_be('topscope') do <<-MANIFEST + $c = "topscope" + class c { } + node default { + include c + notify { 'something': message => $c } + } + MANIFEST + end + end + + it "finds a node scope variable with the same name as a class" do + expect_the_message_to_be('nodescope') do <<-MANIFEST + class c { } + node default { + $c = "nodescope" + include c + notify { 'something': message => $c } + } + MANIFEST + end + end + + it "finds a class variable when the class collides with a nodescope variable" do + expect_the_message_to_be('class') do <<-MANIFEST + class c { $b = "class" } + node default { + $c = "nodescope" + include c + notify { 'something': message => $c::b } + } + MANIFEST + end + end + + it "finds a class variable when the class collides with a topscope variable" do + expect_the_message_to_be('class') do <<-MANIFEST + $c = "topscope" + class c { $b = "class" } + node default { + include c + notify { 'something': message => $::c::b } + } + MANIFEST + end + end + end + describe "when using shadowing and inheritance" do it "finds value define in the inherited node" do expect_the_message_to_be('parent_msg') do <<-MANIFEST diff --git a/spec/integration/resource/catalog_spec.rb b/spec/integration/resource/catalog_spec.rb index 9d5d7ef0b..5877b4984 100755 --- a/spec/integration/resource/catalog_spec.rb +++ b/spec/integration/resource/catalog_spec.rb @@ -2,10 +2,8 @@ require 'spec_helper' describe Puppet::Resource::Catalog do - describe "when pson is available", :if => Puppet.features.pson? do - it "should support pson" do - Puppet::Resource::Catalog.supported_formats.should be_include(:pson) - end + it "should support pson" do + Puppet::Resource::Catalog.supported_formats.should be_include(:pson) end describe "when using the indirector" do diff --git a/spec/integration/type/package_spec.rb b/spec/integration/type/package_spec.rb index bd328b93a..34d648d4d 100755 --- a/spec/integration/type/package_spec.rb +++ b/spec/integration/type/package_spec.rb @@ -11,7 +11,7 @@ describe Puppet::Type.type(:package), "when choosing a default package provider" if Facter.value(:operatingsystem) == 'Solaris' && Puppet::Util::Package.versioncmp(Facter.value(:kernelrelease), '5.11') >= 0 :pkg else - {"Ubuntu" => :apt, "Debian" => :apt, "Darwin" => :pkgdmg, "RedHat" => :up2date, "Fedora" => :yum, "FreeBSD" => :ports, "OpenBSD" => :openbsd, "Solaris" => :sun}[os] + {"Ubuntu" => :apt, "Debian" => :apt, "Darwin" => :pkgdmg, "RedHat" => :up2date, "Fedora" => :yum, "FreeBSD" => :ports, "OpenBSD" => :openbsd, "Solaris" => :sun, "DragonFly" => :pkgin}[os] end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3c9aad056..4f67f7218 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -47,6 +47,17 @@ end RSpec.configure do |config| include PuppetSpec::Fixtures + # Examples or groups can selectively tag themselves as broken. + # For example; + # + # rbv = "#{RUBY_VERSION}-p#{RbConfig::CONFIG['PATCHLEVEL']}" + # describe "mostly working", :broken => false unless rbv == "1.9.3-p327" do + # it "parses a valid IP" do + # IPAddr.new("::2:3:4:5:6:7:8") + # end + # end + config.filter_run_excluding :broken => true + config.mock_with :mocha tmpdir = Dir.mktmpdir("rspecrun") @@ -59,6 +70,8 @@ RSpec.configure do |config| config.formatters.each { |f| f.instance_variable_set(:@output, $stdout) } end + Puppet::Test::TestHelper.initialize + config.before :all do Puppet::Test::TestHelper.before_all_tests() end diff --git a/spec/unit/application/agent_spec.rb b/spec/unit/application/agent_spec.rb index 275a9ad5f..9bcbad6ee 100755 --- a/spec/unit/application/agent_spec.rb +++ b/spec/unit/application/agent_spec.rb @@ -455,7 +455,6 @@ describe Puppet::Application::Agent do describe "when setting up listen" do before :each do - Puppet[:authconfig] = 'auth' FileTest.stubs(:exists?).with('auth').returns(true) File.stubs(:exist?).returns(true) @puppetd.options.stubs(:[]).with(:serve).returns([]) diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb index ce75a6a78..c2a935c62 100755 --- a/spec/unit/application/apply_spec.rb +++ b/spec/unit/application/apply_spec.rb @@ -208,7 +208,7 @@ describe Puppet::Application::Apply do it "should raise an error if we can't find the node" do Puppet::Node.indirection.expects(:find).returns(nil) - lambda { @apply.main }.should raise_error + lambda { @apply.main }.should raise_error(RuntimeError, /Could not find node/) end it "should load custom classes if loadclasses" do diff --git a/spec/unit/application/face_base_spec.rb b/spec/unit/application/face_base_spec.rb index bf27872e6..88b9aeb07 100755 --- a/spec/unit/application/face_base_spec.rb +++ b/spec/unit/application/face_base_spec.rb @@ -58,9 +58,10 @@ describe Puppet::Application::FaceBase do it "should stop if the first thing found is not an action" do app.command_line.stubs(:args).returns %w{banana count_args} + expect { app.run }.to exit_with 1 - @logs.first.should_not be_nil - @logs.first.message.should =~ /has no 'banana' action/ + + @logs.map(&:message).should == ["'basetest' has no 'banana' action. See `puppet help basetest`."] end it "should use the default action if not given any arguments" do @@ -161,12 +162,18 @@ describe Puppet::Application::FaceBase do it "does not skip when a puppet global setting is given as one item" do app.command_line.stubs(:args).returns %w{--confdir=/tmp/puppet foo} - expect { app.preinit; app.parse_options }.not_to raise_error + app.preinit + app.parse_options + app.action.name.should == :foo + app.options.should == {} end it "does not skip when a puppet global setting is given as two items" do app.command_line.stubs(:args).returns %w{--confdir /tmp/puppet foo} - expect { app.preinit; app.parse_options }.not_to raise_error + app.preinit + app.parse_options + app.action.name.should == :foo + app.options.should == {} end { "boolean options before" => %w{--trace foo}, diff --git a/spec/unit/application/indirection_base_spec.rb b/spec/unit/application/indirection_base_spec.rb index 8257657f2..1610f85ff 100755 --- a/spec/unit/application/indirection_base_spec.rb +++ b/spec/unit/application/indirection_base_spec.rb @@ -1,5 +1,6 @@ #! /usr/bin/env ruby require 'spec_helper' +require 'puppet/util/command_line' require 'puppet/application/indirection_base' require 'puppet/indirector/face' @@ -20,8 +21,6 @@ Puppet::Face.register(face) ######################################################################## describe Puppet::Application::IndirectionBase do - subject { Puppet::Application::TestIndirection.new } - it "should accept a terminus command line option" do # It would be nice not to have to stub this, but whatever... writing an # entire indirection stack would cause us more grief. --daniel 2011-03-31 @@ -35,14 +34,11 @@ describe Puppet::Application::IndirectionBase do Puppet::Indirector::Indirection.expects(:instance). with(:test_indirection).returns(terminus) - subject.command_line.instance_variable_set('@args', %w{--terminus foo save bar}) - - # Not a very nice thing. :( - $stderr.stubs(:puts) - Puppet.stubs(:err) + command_line = Puppet::Util::CommandLine.new("puppet", %w{test_indirection --terminus foo save bar}) + application = Puppet::Application::TestIndirection.new(command_line) expect { - subject.run + application.run }.to exit_with 0 end end diff --git a/spec/unit/application/kick_spec.rb b/spec/unit/application/kick_spec.rb index 4b540d496..57217685b 100755 --- a/spec/unit/application/kick_spec.rb +++ b/spec/unit/application/kick_spec.rb @@ -14,8 +14,11 @@ describe Puppet::Application::Kick, :if => Puppet.features.posix? do describe ".new" do it "should take a command-line object as an argument" do - command_line = stub_everything "command_line" - lambda{ Puppet::Application::Kick.new( command_line ) }.should_not raise_error + command_line = Puppet::Util::CommandLine.new("puppet", ['kick', 'myhost']) + app = Puppet::Application::Kick.new(command_line) + + app.command_line.subcommand_name.should == "kick" + app.command_line.args.should == ['myhost'] end end diff --git a/spec/unit/application/master_spec.rb b/spec/unit/application/master_spec.rb index 932f9cfcd..689a6c692 100755 --- a/spec/unit/application/master_spec.rb +++ b/spec/unit/application/master_spec.rb @@ -242,12 +242,6 @@ describe Puppet::Application::Master, :unless => Puppet.features.microsoft_windo Puppet[:manifest] = "site.pp" Puppet.stubs(:err) @master.stubs(:jj) - Puppet.features.stubs(:pson?).returns true - end - - it "should fail if pson isn't available" do - Puppet.features.expects(:pson?).returns false - lambda { @master.compile }.should raise_error end it "should compile a catalog for the specified node" do diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index ccdd6667a..912416d53 100755 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -17,6 +17,20 @@ describe Puppet::Application do end + describe "application commandline" do + it "should not pick up changes to the array of arguments" do + args = %w{subcommand --arg} + command_line = Puppet::Util::CommandLine.new('puppet', args) + app = Puppet::Application.new(command_line) + + args[0] = 'different_subcommand' + args[1] = '--other-arg' + + app.command_line.subcommand_name.should == 'subcommand' + app.command_line.args.should == ['--arg'] + end + end + describe "application defaults" do it "should fail if required app default values are missing" do @app.stubs(:app_defaults).returns({ :foo => 'bar' }) @@ -48,7 +62,9 @@ describe Puppet::Application do value =~ /no such file to load|cannot load such file/ end - expect { @klass.find("ThisShallNeverEverEverExist") }.to raise_error(LoadError) + expect { + @klass.find("ThisShallNeverEverEverExist") + }.to raise_error(LoadError) end it "#12114: should prevent File namespace collisions" do @@ -58,6 +74,27 @@ describe Puppet::Application do end end + describe "#available_application_names" do + it 'should be able to find available application names' do + apps = %w{describe filebucket kick queue resource agent cert apply doc master} + Puppet::Util::Autoload.expects(:files_to_load).returns(apps) + + Puppet::Application.available_application_names.should =~ apps + end + + it 'should find applications from multiple paths' do + Puppet::Util::Autoload.expects(:files_to_load).with('puppet/application').returns(%w{ /a/foo.rb /b/bar.rb }) + + Puppet::Application.available_application_names.should =~ %w{ foo bar } + end + + it 'should return unique application names' do + Puppet::Util::Autoload.expects(:files_to_load).with('puppet/application').returns(%w{ /a/foo.rb /b/foo.rb }) + + Puppet::Application.available_application_names.should == %w{ foo } + end + end + describe ".run_mode" do it "should default to user" do @appclass.run_mode.name.should == :user @@ -103,19 +140,6 @@ describe Puppet::Application do end end - - it "it should not allow initialize_app_defaults to be called multiple times" do - app = Puppet::Application.new - expect { - app.initialize_app_defaults - }.to_not raise_error - - expect { - app.initialize_app_defaults - }.to raise_error - end - - it "should explode when an invalid run mode is set at runtime, for great victory" do expect { class InvalidRunModeTestApp < Puppet::Application diff --git a/spec/unit/face/help_spec.rb b/spec/unit/face/help_spec.rb index 15c2e682e..d81031ee3 100755 --- a/spec/unit/face/help_spec.rb +++ b/spec/unit/face/help_spec.rb @@ -72,7 +72,7 @@ describe Puppet::Face[:help, '0.0.1'] do # that can't be run from the command line, so, rather than iterating # over all available faces, we need to iterate over the subcommands # that are available from the command line. - Puppet::Util::CommandLine.available_subcommands.each do |name| + Puppet::Application.available_application_names.each do |name| next unless help_face.is_face_app?(name) next if help_face.exclude_from_docs?(name) face = Puppet::Face[name, :current] @@ -84,12 +84,10 @@ describe Puppet::Face[:help, '0.0.1'] do end context "face summaries" do - # we need to set a bunk module path here, because without doing so, - # the autoloader will try to use it before it is initialized. - Puppet[:modulepath] = "/dev/null" - - Puppet::Face.faces.each do |name| - it "has a summary for #{name}" do + it "can generate face summaries" do + faces = Puppet::Face.faces + faces.length.should > 0 + faces.each do |name| Puppet::Face[name, :current].should have_a_summary end end diff --git a/spec/unit/indirector/certificate_request/rest_spec.rb b/spec/unit/indirector/certificate_request/rest_spec.rb index 47e19d95e..4949bff76 100755 --- a/spec/unit/indirector/certificate_request/rest_spec.rb +++ b/spec/unit/indirector/certificate_request/rest_spec.rb @@ -19,4 +19,8 @@ describe Puppet::SSL::CertificateRequest::Rest do it "should set port_setting to :ca_port" do Puppet::SSL::CertificateRequest::Rest.port_setting.should == :ca_port end + + it "should use the :ca SRV service" do + Puppet::SSL::CertificateRequest::Rest.srv_service.should == :ca + end end diff --git a/spec/unit/indirector/certificate_revocation_list/rest_spec.rb b/spec/unit/indirector/certificate_revocation_list/rest_spec.rb index 4da306865..f8d37c341 100755 --- a/spec/unit/indirector/certificate_revocation_list/rest_spec.rb +++ b/spec/unit/indirector/certificate_revocation_list/rest_spec.rb @@ -19,4 +19,8 @@ describe Puppet::SSL::CertificateRevocationList::Rest do it "should set port_setting to :ca_port" do Puppet::SSL::CertificateRevocationList::Rest.port_setting.should == :ca_port end + + it "should use the :ca SRV service" do + Puppet::SSL::CertificateRevocationList::Rest.srv_service.should == :ca + end end diff --git a/spec/unit/indirector/certificate_status/rest_spec.rb b/spec/unit/indirector/certificate_status/rest_spec.rb index c09855a6f..33dff7528 100755 --- a/spec/unit/indirector/certificate_status/rest_spec.rb +++ b/spec/unit/indirector/certificate_status/rest_spec.rb @@ -11,4 +11,8 @@ describe "Puppet::CertificateStatus::Rest" do it "should be a terminus on Puppet::SSL::Host" do @terminus.should be_instance_of(Puppet::Indirector::CertificateStatus::Rest) end + + it "should use the :ca SRV service" do + Puppet::Indirector::CertificateStatus::Rest.srv_service.should == :ca + end end diff --git a/spec/unit/indirector/file_metadata/rest_spec.rb b/spec/unit/indirector/file_metadata/rest_spec.rb index a1b6af41e..ddc4d9d7e 100755 --- a/spec/unit/indirector/file_metadata/rest_spec.rb +++ b/spec/unit/indirector/file_metadata/rest_spec.rb @@ -2,7 +2,12 @@ require 'spec_helper' require 'puppet/indirector/file_metadata' +require 'puppet/indirector/file_metadata/rest' describe "Puppet::Indirector::Metadata::Rest" do it "should add the node's cert name to the arguments" + + it "should use the :fileserver SRV service" do + Puppet::Indirector::FileMetadata::Rest.srv_service.should == :fileserver + end end diff --git a/spec/unit/indirector/hiera_spec.rb b/spec/unit/indirector/hiera_spec.rb index 0ab433e21..794a4b01f 100644 --- a/spec/unit/indirector/hiera_spec.rb +++ b/spec/unit/indirector/hiera_spec.rb @@ -96,7 +96,9 @@ describe Puppet::Indirector::Hiera do it "should return a hiera configuration hash" do results = @hiera_class.hiera_config - results.should == default_hiera_config + default_hiera_config.each do |key,value| + results[key].should == value + end results.should be_a_kind_of Hash end diff --git a/spec/unit/indirector/queue_spec.rb b/spec/unit/indirector/queue_spec.rb index b90837199..3711b1846 100755 --- a/spec/unit/indirector/queue_spec.rb +++ b/spec/unit/indirector/queue_spec.rb @@ -25,7 +25,7 @@ class FooExampleData end end -describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do +describe Puppet::Indirector::Queue do before :each do @model = mock 'model' @indirection = stub 'indirection', :name => :my_queue, :register_terminus_type => nil, :model => @model @@ -46,12 +46,6 @@ describe Puppet::Indirector::Queue, :if => Puppet.features.pson? do @request = stub 'request', :key => :me, :instance => @subject end - it "should require PSON" do - Puppet.features.expects(:pson?).returns false - - expect { @store_class.new }.to raise_error(ArgumentError) - end - it 'should use the correct client type and queue' do @store.queue.should == :my_queue @store.client.should be_an_instance_of(Puppet::Indirector::Queue::TestClient) diff --git a/spec/unit/indirector/ssl_file_spec.rb b/spec/unit/indirector/ssl_file_spec.rb index aa4a34971..4cc0e216f 100755 --- a/spec/unit/indirector/ssl_file_spec.rb +++ b/spec/unit/indirector/ssl_file_spec.rb @@ -27,6 +27,12 @@ describe Puppet::Indirector::SslFile do Puppet[:trace] = false end + after :each do + @file_class.store_in nil + @file_class.store_at nil + @file_class.store_ca_at nil + end + it "should use :main and :ssl upon initialization" do Puppet.settings.expects(:use).with(:main, :ssl) @file_class.new @@ -43,11 +49,12 @@ describe Puppet::Indirector::SslFile do end it "should fail if no store directory or file location has been set" do + Puppet.settings.expects(:use).with(:main, :ssl) @file_class.store_in nil @file_class.store_at nil - FileTest.expects(:exists?).with(File.dirname(@path)).at_least(0).returns(true) - Dir.stubs(:mkdir).with(@path) - lambda { @file_class.new }.should raise_error(Puppet::DevError, /No file or directory setting provided/) + expect { + @file_class.new + }.to raise_error(Puppet::DevError, /No file or directory setting provided/) end describe "when managing ssl files" do @@ -113,30 +120,45 @@ describe Puppet::Indirector::SslFile do describe "when finding certificates on disk" do describe "and no certificate is present" do - before do - # Stub things so the case management bits work. - FileTest.stubs(:exist?).with(File.dirname(@certpath)).returns false - FileTest.expects(:exist?).with(@certpath).returns false - end - it "should return nil" do + FileTest.expects(:exist?).with(@path).returns(true) + Dir.expects(:entries).with(@path).returns([]) + FileTest.expects(:exist?).with(@certpath).returns(false) + @searcher.find(@request).should be_nil end end describe "and a certificate is present" do - before do - FileTest.expects(:exist?).with(@certpath).returns true - end + let(:cert) { mock 'cert' } + let(:model) { mock 'model' } - it "should return an instance of the model, which it should use to read the certificate" do - cert = mock 'cert' - model = mock 'model' + before(:each) do @file_class.stubs(:model).returns model + end + + context "is readable" do + it "should return an instance of the model, which it should use to read the certificate" do + FileTest.expects(:exist?).with(@certpath).returns true + + model.expects(:new).with("myname").returns cert + cert.expects(:read).with(@certpath) + + @searcher.find(@request).should equal(cert) + end + end - model.expects(:new).with("myname").returns cert - cert.expects(:read).with(@certpath) - @searcher.find(@request).should equal(cert) + context "is unreadable" do + it "should raise an exception" do + FileTest.expects(:exist?).with(@certpath).returns(true) + + model.expects(:new).with("myname").returns cert + cert.expects(:read).with(@certpath).raises(Errno::EACCES) + + expect { + @searcher.find(@request) + }.to raise_error(Errno::EACCES) + end end end @@ -262,41 +284,46 @@ describe Puppet::Indirector::SslFile do end describe "when searching for certificates" do - before do - @model = mock 'model' - @file_class.stubs(:model).returns @model + let(:one) { stub 'one' } + let(:two) { stub 'two' } + let(:one_path) { File.join(@path, 'one.pem') } + let(:two_path) { File.join(@path, 'two.pem') } + let(:model) { mock 'model' } + + before :each do + @file_class.stubs(:model).returns model end - it "should return a certificate instance for all files that exist" do - Dir.expects(:entries).with(@path).returns %w{one.pem two.pem} - one = stub 'one', :read => nil - two = stub 'two', :read => nil + it "should return a certificate instance for all files that exist" do + Dir.expects(:entries).with(@path).returns(%w{. .. one.pem two.pem}) - @model.expects(:new).with("one").returns one - @model.expects(:new).with("two").returns two + model.expects(:new).with("one").returns one + one.expects(:read).with(one_path) + model.expects(:new).with("two").returns two + two.expects(:read).with(two_path) @searcher.search(@request).should == [one, two] end - it "should read each certificate in using the model's :read method" do - Dir.expects(:entries).with(@path).returns %w{one.pem} - - one = stub 'one' - one.expects(:read).with(File.join(@path, "one.pem")) + it "should raise an exception if any file is unreadable" do + Dir.expects(:entries).with(@path).returns(%w{. .. one.pem two.pem}) - @model.expects(:new).with("one").returns one + model.expects(:new).with("one").returns(one) + one.expects(:read).with(one_path) + model.expects(:new).with("two").returns(two) + two.expects(:read).raises(Errno::EACCES) - @searcher.search(@request) + expect { + @searcher.search(@request) + }.to raise_error(Errno::EACCES) end it "should skip any files that do not match /\.pem$/" do - Dir.expects(:entries).with(@path).returns %w{. .. one.pem} - - one = stub 'one', :read => nil + Dir.expects(:entries).with(@path).returns(%w{. .. one two.notpem}) - @model.expects(:new).with("one").returns one + model.expects(:new).never - @searcher.search(@request) + @searcher.search(@request).should == [] end end end diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb index a79320a45..24cc16ee9 100755 --- a/spec/unit/module_spec.rb +++ b/spec/unit/module_spec.rb @@ -521,7 +521,7 @@ describe Puppet::Module do mod end - describe "when loading the metadata file", :if => Puppet.features.pson? do + describe "when loading the metadata file" do before do @data = { :license => "GPL2", diff --git a/spec/unit/module_tool_spec.rb b/spec/unit/module_tool_spec.rb index 0343984d6..93db99afe 100755 --- a/spec/unit/module_tool_spec.rb +++ b/spec/unit/module_tool_spec.rb @@ -152,93 +152,126 @@ TREE TREE end end + describe '.set_option_defaults' do - include PuppetSpec::Files - let (:setting) { {:environment => "foo", :modulepath => make_absolute("foo")} } + describe 'option :environment' do + context 'passed:' do + let (:environment) { "ahgkduerh" } + let (:options) { {:environment => environment} } - [:environment, :modulepath].each do |value| - describe "if #{value} is part of options" do - let (:options) { {} } + it 'Puppet[:environment] should be set to the value of the option' do + subject.set_option_defaults options - before(:each) do - options[value] = setting[value] - Puppet[value] = "bar" + Puppet[:environment].should == environment end - it "should set Puppet[#{value}] to the options[#{value}]" do + it 'the option value should not be overridden' do + Puppet[:environment] = :foo subject.set_option_defaults options - Puppet[value].should == options[value] + + options[:environment].should == environment + end + end + + context 'NOT passed:' do + it 'Puppet[:environment] should NOT be overridden' do + Puppet[:environment] = :foo + + subject.set_option_defaults({}) + Puppet[:environment].should == :foo end - it "should not override options[#{value}]" do + it 'the option should be set to the value of Puppet[:environment]' do + options_to_modify = Hash.new + Puppet[:environment] = :abcdefg + + subject.set_option_defaults options_to_modify + + options_to_modify[:environment].should == :abcdefg + end + end + end + + describe 'option :modulepath' do + context 'passed:' do + let (:modulepath) { PuppetSpec::Files.make_absolute('/bar') } + let (:options) { {:modulepath => modulepath} } + + it 'Puppet[:modulepath] should be set to the value of the option' do + subject.set_option_defaults options - options[value].should == setting[value] + + Puppet[:modulepath].should == modulepath end + it 'the option value should not be overridden' do + Puppet[:modulepath] = "/foo" + + subject.set_option_defaults options + + options[:modulepath].should == modulepath + end end - describe "if #{value} is not part of options" do - let (:options) { {} } + context 'NOT passed:' do + let (:options) { {:environment => :pmttestenv} } before(:each) do - Puppet[value] = setting[value] + Puppet[:modulepath] = "/no" + Puppet[:environment] = :pmttestenv + Puppet.settings.set_value(:modulepath, + ["/foo", "/bar", "/no"].join(File::PATH_SEPARATOR), + :pmttestenv) end - it "should populate options[#{value}] with the value of Puppet[#{value}]" do + it 'Puppet[:modulepath] should be reset to the module path of the current environment' do subject.set_option_defaults options - Puppet[value].should == options[value] + + Puppet[:modulepath].should == Puppet.settings.value(:modulepath, :pmttestenv) end - it "should not override Puppet[#{value}]" do + it 'the option should be set to the module path of the current environment' do subject.set_option_defaults options - Puppet[value].should == setting[value] + + options[:modulepath].should == Puppet.settings.value(:modulepath, :pmttestenv) end end end - describe ':target_dir' do - let (:sep) { File::PATH_SEPARATOR } + describe 'option :target_dir' do + let (:target_dir) { 'boo' } - let (:my_fake_path) { - ["/my/fake/dir", "/my/other/dir"].collect { |dir| make_absolute(dir) } .join(sep) - } - let (:options) { {:modulepath => my_fake_path}} + context 'passed:' do + let (:options) { {:target_dir => target_dir} } - describe "when not specified" do + it 'the option value should be prepended to the Puppet[:modulepath]' do + Puppet[:modulepath] = "/fuz" + original_modulepath = Puppet[:modulepath] - it "should set options[:target_dir]" do subject.set_option_defaults options - options[:target_dir].should_not be_nil + + Puppet[:modulepath].should == options[:target_dir] + File::PATH_SEPARATOR + original_modulepath end - it "should be the first path of options[:modulepath]" do + it 'the option value should be turned into an absolute path' do subject.set_option_defaults options - options[:target_dir].should == my_fake_path.split(sep).first - end - end - describe "when specified" do - let (:my_target_dir) { make_absolute("/foo/bar") } - before(:each) do - options[:target_dir] = my_target_dir + options[:target_dir].should == File.expand_path(target_dir) end + end - it "should not be overridden" do - subject.set_option_defaults options - options[:target_dir].should == my_target_dir + describe 'NOT passed:' do + before :each do + Puppet[:modulepath] = 'foo' + File::PATH_SEPARATOR + 'bar' end - it "should be prepended to options[:modulepath]" do + it 'the option should be set to the first component of Puppet[:modulepath]' do + options = Hash.new subject.set_option_defaults options - options[:modulepath].split(sep).first.should == my_target_dir - end - it "should leave the remainder of options[:modulepath] untouched" do - subject.set_option_defaults options - options[:modulepath].split(sep).drop(1).join(sep).should == my_fake_path + options[:target_dir].should == Puppet[:modulepath].split(File::PATH_SEPARATOR)[0] end end - end end end diff --git a/spec/unit/network/authstore_spec.rb b/spec/unit/network/authstore_spec.rb index 6d2309c28..54815ca32 100755 --- a/spec/unit/network/authstore_spec.rb +++ b/spec/unit/network/authstore_spec.rb @@ -1,5 +1,6 @@ #! /usr/bin/env ruby require 'spec_helper' +require 'rbconfig' require 'puppet/network/authconfig' @@ -214,7 +215,6 @@ describe Puppet::Network::AuthStore::Declaration do "1::2:3:4", "1::2:3", "1::8", - "::2:3:4:5:6:7:8", "::2:3:4:5:6:7", "::2:3:4:5:6", "::2:3:4:5", @@ -291,6 +291,27 @@ describe Puppet::Network::AuthStore::Declaration do end unless ip =~ /:.*\./ # Hybrid IPs aren't supported by ruby's ipaddr } + [ + "::2:3:4:5:6:7:8", + ].each { |ip| + describe "when the pattern is a valid IP such as #{ip}" do + let(:declaration) do + Puppet::Network::AuthStore::Declaration.new(:allow_ip,ip) + end + + issue_7477 = !(IPAddr.new(ip) rescue false) + + it "should match the specified IP" do + pending "resolution of ruby issue [7477](http://goo.gl/Bb1LU)", :if => issue_7477 + declaration.should be_match('www.testsite.org',ip) + end + it "should not match other IPs" do + pending "resolution of ruby issue [7477](http://goo.gl/Bb1LU)", :if => issue_7477 + declaration.should_not be_match('www.testsite.org','200.101.99.98') + end + end + } + { 'spirit.mars.nasa.gov' => 'a PQDN', 'ratchet.2ndsiteinc.com' => 'a PQDN with digits', diff --git a/spec/unit/network/formats_spec.rb b/spec/unit/network/formats_spec.rb index bd488ad49..df0d62f4d 100755 --- a/spec/unit/network/formats_spec.rb +++ b/spec/unit/network/formats_spec.rb @@ -220,7 +220,7 @@ describe "Puppet Network Format" do Puppet::Network::FormatHandler.format(:pson).should_not be_nil end - describe "pson", :if => Puppet.features.pson? do + describe "pson" do before do @pson = Puppet::Network::FormatHandler.format(:pson) end @@ -311,6 +311,10 @@ describe "Puppet Network Format" do end end + it "should render empty hashes as empty strings" do + subject.render({}).should == '' + end + it "should render a non-trivially-keyed Hash as JSON" do hash = { [1,2] => 3, [2,3] => 5, [3,4] => 7 } subject.render(hash).should == json.render(hash).chomp diff --git a/spec/unit/parser/collector_spec.rb b/spec/unit/parser/collector_spec.rb index 32e7a1c15..132bddbc5 100755 --- a/spec/unit/parser/collector_spec.rb +++ b/spec/unit/parser/collector_spec.rb @@ -34,7 +34,7 @@ describe Puppet::Parser::Collector, "when initializing" do @collector.equery.should equal(@equery) end - it "should canonize the type name" do + it "should canonicalize the type name" do @collector = Puppet::Parser::Collector.new(@scope, "resource::type", @equery, @vquery, @form) @collector.type.should == "Resource::Type" end diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb index a7a6e0074..b16f9111b 100755 --- a/spec/unit/parser/functions/create_resources_spec.rb +++ b/spec/unit/parser/functions/create_resources_spec.rb @@ -19,7 +19,7 @@ describe 'function for dynamically creating resources' do end it 'should require two or three arguments' do - expect { @scope.function_create_resources(['foo']) }.to raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2 or 3)') + expect { @scope.function_create_resources(['foo']) }.to raise_error(ArgumentError, 'create_resources(): Wrong number of arguments given (1 for minimum 2)') expect { @scope.function_create_resources(['foo', 'bar', 'blah', 'baz']) }.to raise_error(ArgumentError, 'create_resources(): wrong number of arguments (4; must be 2 or 3)') end @@ -50,6 +50,17 @@ describe 'function for dynamically creating resources' do catalog.resource(:file, "/etc/foo")['ensure'].should == 'present' end + it 'should be able to add virtual resources' do + catalog = compile_to_catalog("create_resources('@file', {'/etc/foo'=>{'ensure'=>'present'}})\nrealize(File['/etc/foo'])") + catalog.resource(:file, "/etc/foo")['ensure'].should == 'present' + end + + it 'should be able to add exported resources' do + catalog = compile_to_catalog("create_resources('@@file', {'/etc/foo'=>{'ensure'=>'present'}})") + catalog.resource(:file, "/etc/foo")['ensure'].should == 'present' + catalog.resource(:file, "/etc/foo").exported.should == true + end + it 'should accept multiple types' do catalog = compile_to_catalog("create_resources('notify', {'foo'=>{'message'=>'one'}, 'bar'=>{'message'=>'two'}})") catalog.resource(:notify, "foo")['message'].should == 'one' diff --git a/spec/unit/parser/functions/extlookup_spec.rb b/spec/unit/parser/functions/extlookup_spec.rb index 4bc2702b7..fae32fa97 100755 --- a/spec/unit/parser/functions/extlookup_spec.rb +++ b/spec/unit/parser/functions/extlookup_spec.rb @@ -19,12 +19,12 @@ describe "the extlookup function" do Puppet::Parser::Functions.function("extlookup").should == "function_extlookup" end - it "should raise a ParseError if there is less than 1 arguments" do - lambda { @scope.function_extlookup([]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is less than 1 arguments" do + lambda { @scope.function_extlookup([]) }.should( raise_error(ArgumentError)) end - it "should raise a ParseError if there is more than 3 arguments" do - lambda { @scope.function_extlookup(["foo", "bar", "baz", "gazonk"]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is more than 3 arguments" do + lambda { @scope.function_extlookup(["foo", "bar", "baz", "gazonk"]) }.should( raise_error(ArgumentError)) end it "should return the default" do diff --git a/spec/unit/parser/functions/hiera_array_spec.rb b/spec/unit/parser/functions/hiera_array_spec.rb index d9e25cef0..e8efb727f 100644 --- a/spec/unit/parser/functions/hiera_array_spec.rb +++ b/spec/unit/parser/functions/hiera_array_spec.rb @@ -8,7 +8,7 @@ describe 'Puppet::Parser::Functions#hiera_array' do let :scope do Puppet::Parser::Scope.new_for_test_harness('foo') end it 'should require a key argument' do - expect { scope.function_hiera_array([]) }.to raise_error(Puppet::ParseError) + expect { scope.function_hiera_array([]) }.to raise_error(ArgumentError) end it 'should raise a useful error when nil is returned' do diff --git a/spec/unit/parser/functions/hiera_hash_spec.rb b/spec/unit/parser/functions/hiera_hash_spec.rb index c7c9d4432..a345a6c7f 100644 --- a/spec/unit/parser/functions/hiera_hash_spec.rb +++ b/spec/unit/parser/functions/hiera_hash_spec.rb @@ -4,7 +4,7 @@ describe 'Puppet::Parser::Functions#hiera_hash' do let :scope do Puppet::Parser::Scope.new_for_test_harness('foo') end it 'should require a key argument' do - expect { scope.function_hiera_hash([]) }.to raise_error(Puppet::ParseError) + expect { scope.function_hiera_hash([]) }.to raise_error(ArgumentError) end it 'should raise a useful error when nil is returned' do diff --git a/spec/unit/parser/functions/hiera_include_spec.rb b/spec/unit/parser/functions/hiera_include_spec.rb index 3fd7b7740..f06d8c69c 100644 --- a/spec/unit/parser/functions/hiera_include_spec.rb +++ b/spec/unit/parser/functions/hiera_include_spec.rb @@ -10,7 +10,7 @@ describe 'Puppet::Parser::Functions#hiera_include' do end it 'should require a key argument' do - expect { scope.function_hiera_include([]) }.to raise_error(Puppet::ParseError) + expect { scope.function_hiera_include([]) }.to raise_error(ArgumentError) end it 'should raise a useful error when nil is returned' do diff --git a/spec/unit/parser/functions/hiera_spec.rb b/spec/unit/parser/functions/hiera_spec.rb index 657d4f6fb..0abcb1b28 100755 --- a/spec/unit/parser/functions/hiera_spec.rb +++ b/spec/unit/parser/functions/hiera_spec.rb @@ -6,7 +6,7 @@ describe 'Puppet::Parser::Functions#hiera' do let :scope do Puppet::Parser::Scope.new_for_test_harness('foo') end it 'should require a key argument' do - expect { scope.function_hiera([]) }.to raise_error(Puppet::ParseError) + expect { scope.function_hiera([]) }.to raise_error(ArgumentError) end it 'should raise a useful error when nil is returned' do diff --git a/spec/unit/parser/functions/regsubst_spec.rb b/spec/unit/parser/functions/regsubst_spec.rb index 439c16270..c75b16c0e 100755 --- a/spec/unit/parser/functions/regsubst_spec.rb +++ b/spec/unit/parser/functions/regsubst_spec.rb @@ -16,12 +16,12 @@ describe "the regsubst function" do Puppet::Parser::Functions.function("regsubst").should == "function_regsubst" end - it "should raise a ParseError if there is less than 3 arguments" do - lambda { @scope.function_regsubst(["foo", "bar"]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is less than 3 arguments" do + lambda { @scope.function_regsubst(["foo", "bar"]) }.should( raise_error(ArgumentError)) end - it "should raise a ParseError if there is more than 5 arguments" do - lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "del", "x", "y"]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is more than 5 arguments" do + lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "del", "x", "y"]) }.should( raise_error(ArgumentError)) end diff --git a/spec/unit/parser/functions/split_spec.rb b/spec/unit/parser/functions/split_spec.rb index 20a6f4204..5ddbe8d44 100755 --- a/spec/unit/parser/functions/split_spec.rb +++ b/spec/unit/parser/functions/split_spec.rb @@ -16,12 +16,12 @@ describe "the split function" do Puppet::Parser::Functions.function("split").should == "function_split" end - it "should raise a ParseError if there is less than 2 arguments" do - lambda { @scope.function_split(["foo"]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is less than 2 arguments" do + lambda { @scope.function_split(["foo"]) }.should( raise_error(ArgumentError)) end - it "should raise a ParseError if there is more than 2 arguments" do - lambda { @scope.function_split(["foo", "bar", "gazonk"]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is more than 2 arguments" do + lambda { @scope.function_split(["foo", "bar", "gazonk"]) }.should( raise_error(ArgumentError)) end it "should raise a RegexpError if the regexp is malformed" do diff --git a/spec/unit/parser/functions/sprintf_spec.rb b/spec/unit/parser/functions/sprintf_spec.rb index e1d738e66..36c0ae1b7 100755 --- a/spec/unit/parser/functions/sprintf_spec.rb +++ b/spec/unit/parser/functions/sprintf_spec.rb @@ -16,8 +16,8 @@ describe "the sprintf function" do Puppet::Parser::Functions.function("sprintf").should == "function_sprintf" end - it "should raise a ParseError if there is less than 1 argument" do - lambda { @scope.function_sprintf([]) }.should( raise_error(Puppet::ParseError)) + it "should raise a ArgumentError if there is less than 1 argument" do + lambda { @scope.function_sprintf([]) }.should( raise_error(ArgumentError)) end it "should format integers" do diff --git a/spec/unit/parser/functions/versioncmp_spec.rb b/spec/unit/parser/functions/versioncmp_spec.rb index 5a6668678..760a286c5 100755 --- a/spec/unit/parser/functions/versioncmp_spec.rb +++ b/spec/unit/parser/functions/versioncmp_spec.rb @@ -16,12 +16,12 @@ describe "the versioncmp function" do Puppet::Parser::Functions.function("versioncmp").should == "function_versioncmp" end - it "should raise a ParseError if there is less than 2 arguments" do - lambda { @scope.function_versioncmp(["1.2"]) }.should raise_error(Puppet::ParseError) + it "should raise a ArgumentError if there is less than 2 arguments" do + lambda { @scope.function_versioncmp(["1.2"]) }.should raise_error(ArgumentError) end - it "should raise a ParseError if there is more than 2 arguments" do - lambda { @scope.function_versioncmp(["1.2", "2.4.5", "3.5.6"]) }.should raise_error(Puppet::ParseError) + it "should raise a ArgumentError if there is more than 2 arguments" do + lambda { @scope.function_versioncmp(["1.2", "2.4.5", "3.5.6"]) }.should raise_error(ArgumentError) end it "should call Puppet::Util::Package.versioncmp (included in scope)" do diff --git a/spec/unit/parser/functions_spec.rb b/spec/unit/parser/functions_spec.rb index ef50447da..1430ff26f 100755 --- a/spec/unit/parser/functions_spec.rb +++ b/spec/unit/parser/functions_spec.rb @@ -39,7 +39,7 @@ describe Puppet::Parser::Functions do end end - describe "when calling function to test function existance" do + describe "when calling function to test function existence" do before do @module = Module.new Puppet::Parser::Functions.stubs(:environment_module).returns @module @@ -64,6 +64,56 @@ describe Puppet::Parser::Functions do end end + describe "when calling function to test arity" do + before :each do + Puppet::Node::Environment.stubs(:current).returns(nil) + @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo")) + @scope = Puppet::Parser::Scope.new(@compiler) + end + + it "should raise an error if the function is called with too many arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| } + lambda { @scope.function_name([1,2,3]) }.should raise_error ArgumentError + end + + it "should raise an error if the function is called with too few arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| } + lambda { @scope.function_name([1]) }.should raise_error ArgumentError + end + + it "should not raise an error if the function is called with correct number of arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| } + lambda { @scope.function_name([1,2]) }.should_not raise_error ArgumentError + end + + it "should raise an error if the variable arg function is called with too few arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| } + lambda { @scope.function_name([1]) }.should raise_error ArgumentError + end + + it "should not raise an error if the variable arg function is called with correct number of arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| } + lambda { @scope.function_name([1,2]) }.should_not raise_error ArgumentError + end + + it "should not raise an error if the variable arg function is called with more number of arguments" do + Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| } + lambda { @scope.function_name([1,2,3]) }.should_not raise_error ArgumentError + end + end + + describe "::arity" do + it "returns the given arity of a function" do + Puppet::Parser::Functions.newfunction("name", :arity => 4) { |args| } + Puppet::Parser::Functions.arity(:name).should == 4 + end + + it "returns -1 if no arity is given" do + Puppet::Parser::Functions.newfunction("name") { |args| } + Puppet::Parser::Functions.arity(:name).should == -1 + end + end + describe "::get_function" do it "can retrieve a function defined on the *root* environment" do Thread.current[:environment] = nil diff --git a/spec/unit/parser/type_loader_spec.rb b/spec/unit/parser/type_loader_spec.rb index 918770c71..e15c05fea 100755 --- a/spec/unit/parser/type_loader_spec.rb +++ b/spec/unit/parser/type_loader_spec.rb @@ -11,6 +11,7 @@ describe Puppet::Parser::TypeLoader do before do @loader = Puppet::Parser::TypeLoader.new(:myenv) + Puppet.expects(:deprecation_warning).never end it "should support an environment" do @@ -146,6 +147,8 @@ describe Puppet::Parser::TypeLoader do end it "should load all ruby manifests from all modules in the specified environment" do + Puppet.expects(:deprecation_warning).at_least(1) + @module1 = mk_module(@modulebase1, "one") @module2 = mk_module(@modulebase2, "two") diff --git a/spec/unit/provider/augeas/augeas_spec.rb b/spec/unit/provider/augeas/augeas_spec.rb index 53d8e8521..77a1621f6 100755 --- a/spec/unit/provider/augeas/augeas_spec.rb +++ b/spec/unit/provider/augeas/augeas_spec.rb @@ -570,6 +570,7 @@ describe provider_class do it "should handle setm commands" do @resource[:changes] = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","setm test Jar/Jar Binks"] @resource[:context] = "/foo/" + @augeas.expects(:respond_to?).with("setm").returns(true) @augeas.expects(:set).with("/foo/test[1]/Jar/Jar", "Foo").returns(true) @augeas.expects(:set).with("/foo/test[2]/Jar/Jar", "Bar").returns(true) @augeas.expects(:setm).with("/foo/test", "Jar/Jar", "Binks").returns(true) @@ -577,6 +578,36 @@ describe provider_class do @augeas.expects(:close) @provider.execute_changes.should == :executed end + + it "should throw error if setm command not supported" do + @resource[:changes] = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","setm test Jar/Jar Binks"] + @resource[:context] = "/foo/" + @augeas.expects(:respond_to?).with("setm").returns(false) + @augeas.expects(:set).with("/foo/test[1]/Jar/Jar", "Foo").returns(true) + @augeas.expects(:set).with("/foo/test[2]/Jar/Jar", "Bar").returns(true) + expect { @provider.execute_changes }.to raise_error RuntimeError, /command 'setm' not supported/ + end + + it "should handle clearm commands" do + @resource[:changes] = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","clearm test Jar/Jar"] + @resource[:context] = "/foo/" + @augeas.expects(:respond_to?).with("clearm").returns(true) + @augeas.expects(:set).with("/foo/test[1]/Jar/Jar", "Foo").returns(true) + @augeas.expects(:set).with("/foo/test[2]/Jar/Jar", "Bar").returns(true) + @augeas.expects(:clearm).with("/foo/test", "Jar/Jar").returns(true) + @augeas.expects(:save).returns(true) + @augeas.expects(:close) + @provider.execute_changes.should == :executed + end + + it "should throw error if clearm command not supported" do + @resource[:changes] = ["set test[1]/Jar/Jar Foo","set test[2]/Jar/Jar Bar","clearm test Jar/Jar"] + @resource[:context] = "/foo/" + @augeas.expects(:respond_to?).with("clearm").returns(false) + @augeas.expects(:set).with("/foo/test[1]/Jar/Jar", "Foo").returns(true) + @augeas.expects(:set).with("/foo/test[2]/Jar/Jar", "Bar").returns(true) + expect { @provider.execute_changes }.to raise_error RuntimeError, /command 'clearm' not supported/ + end end describe "when making changes", :if => Puppet.features.augeas? do diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb index 5085af105..55ff321d0 100755 --- a/spec/unit/provider/package/apt_spec.rb +++ b/spec/unit/provider/package/apt_spec.rb @@ -76,8 +76,6 @@ Version table: @provider.run_preseed end - it "should fail if a cdrom is listed in the sources list and :allowcdrom is not specified" - describe "when installing" do it "should preseed if a responsefile is provided" do @resource.expects(:[]).with(:responsefile).returns "/my/file" diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb index 37f61f69a..42d24e37f 100755 --- a/spec/unit/provider/package/openbsd_spec.rb +++ b/spec/unit/provider/package/openbsd_spec.rb @@ -5,11 +5,36 @@ require 'stringio' provider_class = Puppet::Type.type(:package).provider(:openbsd) describe provider_class do - subject { provider_class } + let(:package) { Puppet::Type.type(:package).new(:name => 'bash', :provider => 'openbsd') } + let(:provider) { provider_class.new(package) } - def package(args = {}) - defaults = { :name => 'bash', :provider => 'openbsd' } - Puppet::Type.type(:package).new(defaults.merge(args)) + def expect_read_from_pkgconf(lines) + pkgconf = stub(:readlines => lines) + File.expects(:exist?).with('/etc/pkg.conf').returns(true) + File.expects(:open).with('/etc/pkg.conf', 'rb').returns(pkgconf) + end + + def expect_pkgadd_with_source(source) + provider.expects(:pkgadd).with do |fullname| + ENV.should_not be_key 'PKG_PATH' + fullname.should == source + end + end + + def expect_pkgadd_with_env_and_name(source, &block) + ENV.should_not be_key 'PKG_PATH' + + provider.expects(:pkgadd).with do |fullname| + ENV.should be_key 'PKG_PATH' + ENV['PKG_PATH'].should == source + + fullname.should == provider.resource[:name] + end + provider.expects(:execpipe).with(['/bin/pkg_info', '-I', provider.resource[:name]]).yields('') + + yield + + ENV.should_not be_key 'PKG_PATH' end before :each do @@ -22,78 +47,167 @@ describe provider_class do context "::instances" do it "should return nil if execution failed" do - subject.expects(:execpipe).raises(Puppet::ExecutionFailure, 'wawawa') - subject.instances.should be_nil + provider_class.expects(:execpipe).raises(Puppet::ExecutionFailure, 'wawawa') + provider_class.instances.should be_nil end it "should return the empty set if no packages are listed" do - subject.expects(:execpipe).with(%w{/bin/pkg_info -a}).yields(StringIO.new('')) - subject.instances.should be_empty + provider_class.expects(:execpipe).with(%w{/bin/pkg_info -a}).yields(StringIO.new('')) + provider_class.instances.should be_empty end it "should return all packages when invoked" do fixture = File.read(my_fixture('pkginfo.list')) - subject.expects(:execpipe).with(%w{/bin/pkg_info -a}).yields(fixture) - subject.instances.map(&:name).sort.should == + provider_class.expects(:execpipe).with(%w{/bin/pkg_info -a}).yields(fixture) + provider_class.instances.map(&:name).sort.should == %w{bash bzip2 expat gettext libiconv lzo openvpn python vim wget}.sort end end context "#install" do it "should fail if the resource doesn't have a source" do - provider = subject.new(package()) - expect { provider.install }. - to raise_error Puppet::Error, /must specify a package source/ + File.expects(:exist?).with('/etc/pkg.conf').returns(false) + + expect { + provider.install + }.to raise_error Puppet::Error, /must specify a package source/ end - it "should install correctly when given a directory-unlike source" do - ENV.should_not be_key 'PKG_PATH' + it "should fail if /etc/pkg.conf exists, but is not readable" do + File.expects(:exist?).with('/etc/pkg.conf').returns(true) + File.expects(:open).with('/etc/pkg.conf', 'rb').raises(Errno::EACCES) + expect { + provider.install + }.to raise_error Errno::EACCES, /Permission denied/ + end + + it "should fail if /etc/pkg.conf exists, but there is no installpath" do + expect_read_from_pkgconf([]) + expect { + provider.install + }.to raise_error Puppet::Error, /No valid installpath found in \/etc\/pkg\.conf and no source was set/ + end + + it "should install correctly when given a directory-unlike source" do source = '/whatever.pkg' - provider = subject.new(package(:source => source)) - provider.expects(:pkgadd).with do |name| - ENV.should_not be_key 'PKG_PATH' - name == source - end + provider.resource[:source] = source + expect_pkgadd_with_source(source) provider.install - ENV.should_not be_key 'PKG_PATH' end it "should install correctly when given a directory-like source" do - ENV.should_not be_key 'PKG_PATH' - source = '/whatever/' - provider = subject.new(package(:source => source)) - provider.expects(:pkgadd).with do |name| - ENV.should be_key 'PKG_PATH' - ENV['PKG_PATH'].should == source + provider.resource[:source] = source + expect_pkgadd_with_env_and_name(source) do + provider.install + end + end - name == provider.resource[:name] + it "should install correctly when given a CDROM installpath" do + dir = '/mnt/cdrom/5.2/packages/amd64/' + expect_read_from_pkgconf(["installpath = #{dir}"]) + expect_pkgadd_with_env_and_name(dir) do + provider.install end - provider.expects(:execpipe).with(%w{/bin/pkg_info -I bash}).yields('') + end + + it "should install correctly when given a ftp mirror" do + url = 'ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/' + expect_read_from_pkgconf(["installpath = #{url}"]) + expect_pkgadd_with_env_and_name(url) do + provider.install + end + end + + it "should set the resource's source parameter" do + url = 'ftp://your.ftp.mirror/pub/OpenBSD/5.2/packages/amd64/' + expect_read_from_pkgconf(["installpath = #{url}"]) + expect_pkgadd_with_env_and_name(url) do + provider.install + end + + provider.resource[:source].should == url + end + + it "should strip leading whitespace in installpath" do + dir = '/one/' + lines = ["# Notice the extra spaces after the ='s\n", + "installpath = #{dir}\n", + "# And notice how each line ends with a newline\n"] + + expect_read_from_pkgconf(lines) + expect_pkgadd_with_env_and_name(dir) do + provider.install + end + end + + it "should not require spaces around the equals" do + dir = '/one/' + lines = ["installpath=#{dir}"] + + expect_read_from_pkgconf(lines) + expect_pkgadd_with_env_and_name(dir) do + provider.install + end + end + + it "should be case-insensitive" do + dir = '/one/' + lines = ["INSTALLPATH = #{dir}"] + + expect_read_from_pkgconf(lines) + expect_pkgadd_with_env_and_name(dir) do + provider.install + end + end + + it "should ignore unknown keywords" do + dir = '/one/' + lines = ["foo = bar\n", + "installpath = #{dir}\n"] + + expect_read_from_pkgconf(lines) + expect_pkgadd_with_env_and_name(dir) do + provider.install + end + end + + it "should preserve trailing spaces" do + dir = '/one/ ' + lines = ["installpath = #{dir}"] + + expect_read_from_pkgconf(lines) + expect_pkgadd_with_source(dir) provider.install - ENV.should_not be_key 'PKG_PATH' + end + + %w{ installpath installpath= }.each do |line| + it "should reject '#{line}'" do + expect_read_from_pkgconf([line]) + expect { + provider.install + }.to raise_error(Puppet::Error, /No valid installpath found in \/etc\/pkg\.conf and no source was set/) + end end end context "#get_version" do it "should return nil if execution fails" do - provider = subject.new(package) provider.expects(:execpipe).raises(Puppet::ExecutionFailure, 'wawawa') provider.get_version.should be_nil end it "should return the package version if in the output" do fixture = File.read(my_fixture('pkginfo.list')) - provider = subject.new(package(:name => 'bash')) provider.expects(:execpipe).with(%w{/bin/pkg_info -I bash}).yields(fixture) provider.get_version.should == '3.1.17' end it "should return the empty string if the package is not present" do - provider = subject.new(package(:name => 'zsh')) + provider.resource[:name] = 'zsh' provider.expects(:execpipe).with(%w{/bin/pkg_info -I zsh}).yields(StringIO.new('')) provider.get_version.should == '' end @@ -102,13 +216,12 @@ describe provider_class do context "#query" do it "should return the installed version if present" do fixture = File.read(my_fixture('pkginfo.detail')) - provider = subject.new(package(:name => 'bash')) provider.expects(:pkginfo).with('bash').returns(fixture) provider.query.should == { :ensure => '3.1.17' } end it "should return nothing if not present" do - provider = subject.new(package(:name => 'zsh')) + provider.resource[:name] = 'zsh' provider.expects(:pkginfo).with('zsh').returns('') provider.query.should be_nil end diff --git a/spec/unit/provider/package/pip_spec.rb b/spec/unit/provider/package/pip_spec.rb index 2129da362..2213b6f63 100755 --- a/spec/unit/provider/package/pip_spec.rb +++ b/spec/unit/provider/package/pip_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' provider_class = Puppet::Type.type(:package).provider(:pip) +osfamilies = { 'RedHat' => 'pip-python', 'Not RedHat' => 'pip' } describe provider_class do @@ -30,19 +31,36 @@ describe provider_class do end - describe "instances" do + describe "cmd" do + it "should return pip-python on RedHat systems" do + Facter.stubs(:value).with(:osfamily).returns("RedHat") + provider_class.cmd.should == 'pip-python' + end - it "should return an array when pip is present" do - provider_class.expects(:which).with('pip').returns("/fake/bin/pip") - p = stub("process") - p.expects(:collect).yields("real_package==1.2.5") - provider_class.expects(:execpipe).with("/fake/bin/pip freeze").yields(p) - provider_class.instances + it "should return pip by default" do + Facter.stubs(:value).with(:osfamily).returns("Not RedHat") + provider_class.cmd.should == 'pip' end - it "should return an empty array when pip is missing" do - provider_class.expects(:which).with('pip').returns nil - provider_class.instances.should == [] + end + + describe "instances" do + + osfamilies.each do |osfamily, pip_cmd| + it "should return an array on #{osfamily} when #{pip_cmd} is present" do + Facter.stubs(:value).with(:osfamily).returns(osfamily) + provider_class.expects(:which).with(pip_cmd).returns("/fake/bin/pip") + p = stub("process") + p.expects(:collect).yields("real_package==1.2.5") + provider_class.expects(:execpipe).with("/fake/bin/pip freeze").yields(p) + provider_class.instances + end + + it "should return an empty array on #{osfamily} when #{pip_cmd} is missing" do + Facter.stubs(:value).with(:osfamily).returns(osfamily) + provider_class.expects(:which).with(pip_cmd).returns nil + provider_class.instances.should == [] + end end end @@ -109,11 +127,21 @@ describe provider_class do @provider.install end + it "omits the -e flag (GH-1256)" do + # The -e flag makes the provider non-idempotent + @resource[:ensure] = :installed + @resource[:source] = @url + @provider.expects(:lazy_pip).with() do |*args| + not args.include?("-e") + end + @provider.install + end + it "should install from SCM" do @resource[:ensure] = :installed @resource[:source] = @url @provider.expects(:lazy_pip). - with("install", '-q', '-e', "#{@url}#egg=fake_package") + with("install", '-q', "#{@url}#egg=fake_package") @provider.install end @@ -121,7 +149,7 @@ describe provider_class do @resource[:ensure] = "0123456" @resource[:source] = @url @provider.expects(:lazy_pip). - with("install", "-q", "-e", "#{@url}@0123456#egg=fake_package") + with("install", "-q", "#{@url}@0123456#egg=fake_package") @provider.install end @@ -169,23 +197,29 @@ describe provider_class do @provider.method(:lazy_pip).call "freeze" end - it "should retry if pip has not yet been found" do - @provider.expects(:pip).twice.with('freeze').raises(NoMethodError).then.returns(nil) - @provider.expects(:which).with('pip').returns("/fake/bin/pip") - @provider.method(:lazy_pip).call "freeze" - end - - it "should fail if pip is missing" do - @provider.expects(:pip).with('freeze').raises(NoMethodError) - @provider.expects(:which).with('pip').returns(nil) - expect { @provider.method(:lazy_pip).call("freeze") }.to raise_error(NoMethodError) - end + osfamilies.each do |osfamily, pip_cmd| + it "should retry on #{osfamily} if #{pip_cmd} has not yet been found" do + Facter.stubs(:value).with(:osfamily).returns(osfamily) + @provider.expects(:pip).twice.with('freeze').raises(NoMethodError).then.returns(nil) + @provider.expects(:which).with(pip_cmd).returns("/fake/bin/pip") + @provider.method(:lazy_pip).call "freeze" + end + + it "should fail on #{osfamily} if #{pip_cmd} is missing" do + Facter.stubs(:value).with(:osfamily).returns(osfamily) + @provider.expects(:pip).with('freeze').raises(NoMethodError) + @provider.expects(:which).with(pip_cmd).returns(nil) + expect { @provider.method(:lazy_pip).call("freeze") }.to raise_error(NoMethodError) + end + + it "should output a useful error message on #{osfamily} if #{pip_cmd} is missing" do + Facter.stubs(:value).with(:osfamily).returns(osfamily) + @provider.expects(:pip).with('freeze').raises(NoMethodError) + @provider.expects(:which).with(pip_cmd).returns(nil) + expect { @provider.method(:lazy_pip).call("freeze") }. + to raise_error(NoMethodError, 'Could not locate the pip command.') + end - it "should output a useful error message if pip is missing" do - @provider.expects(:pip).with('freeze').raises(NoMethodError) - @provider.expects(:which).with('pip').returns(nil) - expect { @provider.method(:lazy_pip).call("freeze") }. - to raise_error(NoMethodError, 'Could not locate the pip command.') end end diff --git a/spec/unit/provider/package/portage_spec.rb b/spec/unit/provider/package/portage_spec.rb new file mode 100644 index 000000000..48726918c --- /dev/null +++ b/spec/unit/provider/package/portage_spec.rb @@ -0,0 +1,65 @@ +#! /usr/bin/env ruby + +require 'spec_helper' + +provider = Puppet::Type.type(:package).provider(:portage) + +describe provider do + before do + packagename="sl" + @resource = stub('resource', :[] => packagename,:should => true) + @provider = provider.new(@resource) + + portage = stub(:executable => "foo",:execute => true) + Puppet::Provider::CommandDefiner.stubs(:define).returns(portage) + + @nomatch_result = "" + @match_result = "app-misc sl [] [] http://www.tkl.iis.u-tokyo.ac.jp/~toyoda/index_e.html http://www.izumix.org.uk/sl/ sophisticated graphical program which corrects your miss typing\n" + end + + it "is versionable" do + provider.should be_versionable + end + + it "uses :emerge to install packages" do + @provider.expects(:emerge) + + @provider.install + end + + it "uses query to find the latest package" do + @provider.expects(:query).returns({:versions_available => "myversion"}) + + @provider.latest + end + + it "uses eix to search the lastest version of a package" do + @provider.stubs(:update_eix) + @provider.expects(:eix).returns(StringIO.new(@match_result)) + + @provider.query + end + + it "eix arguments must not include --stable" do + @provider.class.eix_search_arguments.should_not include("--stable") + end + + it "eix arguments must not include --exact" do + @provider.class.eix_search_arguments.should_not include("--exact") + end + + it "query uses default arguments" do + @provider.stubs(:update_eix) + @provider.expects(:eix).returns(StringIO.new(@match_result)) + @provider.class.expects(:eix_search_arguments).returns([]) + + @provider.query + end + + it "can handle search output with empty square brackets" do + @provider.stubs(:update_eix) + @provider.expects(:eix).returns(StringIO.new(@match_result)) + + @provider.query[:name].should eq("sl") + end +end diff --git a/spec/unit/provider/service/freebsd_spec.rb b/spec/unit/provider/service/freebsd_spec.rb index ed5452295..0f523e84f 100755 --- a/spec/unit/provider/service/freebsd_spec.rb +++ b/spec/unit/provider/service/freebsd_spec.rb @@ -35,6 +35,14 @@ OUTPUT @provider.rcvar.should == ['# ntpd', 'ntpd_enable="YES"', '# (default: "")'] end + it "should correctly parse rcvar for DragonFly BSD" do + @provider.stubs(:execute).returns <<OUTPUT +# ntpd +$ntpd=YES +OUTPUT + @provider.rcvar.should == ['# ntpd', 'ntpd=YES'] + end + it "should find the right rcvar_value for FreeBSD < 7" do @provider.stubs(:rcvar).returns(['# ntpd', 'ntpd_enable=YES']) diff --git a/spec/unit/provider/service/gentoo_spec.rb b/spec/unit/provider/service/gentoo_spec.rb index 963bb6471..dab315537 100755 --- a/spec/unit/provider/service/gentoo_spec.rb +++ b/spec/unit/provider/service/gentoo_spec.rb @@ -72,12 +72,12 @@ describe Puppet::Type.type(:service).provider(:gentoo) do describe "#start" do it "should use the supplied start command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :start => '/bin/foo')) - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.start end it "should start the service with <initscript> start otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) - provider.expects(:execute).with(['/etc/init.d/sshd',:start], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:start], :failonfail => true, :override_locale => false, :squelch => true) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') provider.start end @@ -86,12 +86,12 @@ describe Puppet::Type.type(:service).provider(:gentoo) do describe "#stop" do it "should use the supplied stop command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :stop => '/bin/foo')) - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.stop end it "should stop the service with <initscript> stop otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) - provider.expects(:execute).with(['/etc/init.d/sshd',:stop], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:stop], :failonfail => true, :override_locale => false, :squelch => true) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') provider.stop end @@ -153,23 +153,23 @@ describe Puppet::Type.type(:service).provider(:gentoo) do describe "when a special status command is specified" do it "should use the status command from the resource" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) provider.status end it "should return :stopped when the status command returns with a non-zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 3 provider.status.should == :stopped end it "should return :running when the status command returns with a zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 0 provider.status.should == :running end @@ -178,14 +178,14 @@ describe Puppet::Type.type(:service).provider(:gentoo) do describe "when hasstatus is false" do it "should return running if a pid can be found" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never provider.expects(:getpid).returns 1000 provider.status.should == :running end it "should return stopped if no pid can be found" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never provider.expects(:getpid).returns nil provider.status.should == :stopped end @@ -195,7 +195,7 @@ describe Puppet::Type.type(:service).provider(:gentoo) do it "should return running if <initscript> status exits with a zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 0 provider.status.should == :running end @@ -203,7 +203,7 @@ describe Puppet::Type.type(:service).provider(:gentoo) do it "should return stopped if <initscript> status exits with a non-zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') - provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:status], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 3 provider.status.should == :stopped end @@ -213,24 +213,24 @@ describe Puppet::Type.type(:service).provider(:gentoo) do describe "#restart" do it "should use the supplied restart command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :restart => '/bin/foo')) - provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end it "should restart the service with <initscript> restart if hasrestart is true" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => true)) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') - provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end it "should restart the service with <initscript> stop/start if hasrestart is false" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => false)) provider.expects(:search).with('sshd').returns('/etc/init.d/sshd') - provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :squelch => true).never - provider.expects(:execute).with(['/etc/init.d/sshd',:stop], :failonfail => true, :squelch => true) - provider.expects(:execute).with(['/etc/init.d/sshd',:start], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/etc/init.d/sshd',:stop], :failonfail => true, :override_locale => false, :squelch => true) + provider.expects(:execute).with(['/etc/init.d/sshd',:start], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end end diff --git a/spec/unit/provider/service/launchd_spec.rb b/spec/unit/provider/service/launchd_spec.rb index 8b6fa9d5f..dd22c81a0 100755 --- a/spec/unit/provider/service/launchd_spec.rb +++ b/spec/unit/provider/service/launchd_spec.rb @@ -60,7 +60,6 @@ describe Puppet::Type.type(:service).provider(:launchd) do provider.expects(:get_macosx_version_major).returns("10.6") subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => true}]) provider.expects(:read_plist).returns({joblabel => {"Disabled" => false}}) - provider.stubs(:launchd_overrides).returns(launchd_overrides) FileTest.expects(:file?).with(launchd_overrides).returns(true) subject.enabled?.should == :true end @@ -68,7 +67,6 @@ describe Puppet::Type.type(:service).provider(:launchd) do provider.expects(:get_macosx_version_major).returns("10.6") subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}]) provider.expects(:read_plist).returns({joblabel => {"Disabled" => true}}) - provider.stubs(:launchd_overrides).returns(launchd_overrides) FileTest.expects(:file?).with(launchd_overrides).returns(true) subject.enabled?.should == :false end @@ -76,7 +74,6 @@ describe Puppet::Type.type(:service).provider(:launchd) do provider.expects(:get_macosx_version_major).returns("10.6") subject.expects(:plist_from_label).returns([joblabel, {}]) provider.expects(:read_plist).returns({}) - provider.stubs(:launchd_overrides).returns(launchd_overrides) FileTest.expects(:file?).with(launchd_overrides).returns(true) subject.enabled?.should == :true end @@ -122,6 +119,12 @@ describe Puppet::Type.type(:service).provider(:launchd) do subject.expects(:execute).with([:launchctl, :load, '-w', joblabel]) subject.start end + + it "(#16271) Should stop and start the service when a restart is called" do + subject.expects(:stop) + subject.expects(:start) + subject.restart + end end describe "when stopping the service" do @@ -191,7 +194,6 @@ describe Puppet::Type.type(:service).provider(:launchd) do resource[:enable] = true provider.expects(:get_macosx_version_major).returns("10.6") provider.expects(:read_plist).returns({}) - provider.stubs(:launchd_overrides).returns(launchd_overrides) Plist::Emit.expects(:save_plist).once subject.enable end @@ -202,7 +204,6 @@ describe Puppet::Type.type(:service).provider(:launchd) do resource[:enable] = false provider.stubs(:get_macosx_version_major).returns("10.6") provider.stubs(:read_plist).returns({}) - provider.stubs(:launchd_overrides).returns(launchd_overrides) Plist::Emit.expects(:save_plist).once subject.enable end diff --git a/spec/unit/provider/service/openrc_spec.rb b/spec/unit/provider/service/openrc_spec.rb index 489807fe2..aa8162226 100755 --- a/spec/unit/provider/service/openrc_spec.rb +++ b/spec/unit/provider/service/openrc_spec.rb @@ -35,12 +35,12 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "#start" do it "should use the supplied start command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :start => '/bin/foo')) - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.start end it "should start the service with rc-service start otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :override_locale => false, :squelch => true) provider.start end end @@ -48,12 +48,12 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "#stop" do it "should use the supplied stop command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :stop => '/bin/foo')) - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.stop end it "should stop the service with rc-service stop otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :override_locale => false, :squelch => true) provider.stop end end @@ -128,23 +128,23 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "when a special status command if specified" do it "should use the status command from the resource" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) provider.status end it "should return :stopped when status command returns with a non-zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 3 provider.status.should == :stopped end it "should return :running when status command returns with a zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 0 provider.status.should == :running end @@ -153,14 +153,14 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "when hasstatus is false" do it "should return running if a pid can be found" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never provider.expects(:getpid).returns 1000 provider.status.should == :running end it "should return stopped if no pid can be found" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => false)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true).never + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true).never provider.expects(:getpid).returns nil provider.status.should == :stopped end @@ -169,14 +169,14 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "when hasstatus is true" do it "should return running if rc-service status exits with a zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 0 provider.status.should == :running end it "should return stopped if rc-service status exits with a non-zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasstatus => true)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:status], :failonfail => false, :override_locale => false, :squelch => true) $CHILD_STATUS.stubs(:exitstatus).returns 3 provider.status.should == :stopped end @@ -186,22 +186,22 @@ describe Puppet::Type.type(:service).provider(:openrc) do describe "#restart" do it "should use the supplied restart command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :restart => '/bin/foo')) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true).never - provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end it "should restart the service with rc-service restart if hasrestart is true" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => true)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end it "should restart the service with rc-service stop/start if hasrestart is false" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => false)) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :squelch => true).never - provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :squelch => true) - provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:restart], :failonfail => true, :override_locale => false, :squelch => true).never + provider.expects(:execute).with(['/sbin/rc-service','sshd',:stop], :failonfail => true, :override_locale => false, :squelch => true) + provider.expects(:execute).with(['/sbin/rc-service','sshd',:start], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end end diff --git a/spec/unit/provider/service/src_spec.rb b/spec/unit/provider/service/src_spec.rb index 9f6f6c917..8d857a060 100755 --- a/spec/unit/provider/service/src_spec.rb +++ b/spec/unit/provider/service/src_spec.rb @@ -35,12 +35,12 @@ describe provider_class do end it "should execute the startsrc command" do - @provider.expects(:execute).with(['/usr/bin/startsrc', '-s', "myservice"], {:squelch => true, :failonfail => true}) + @provider.expects(:execute).with(['/usr/bin/startsrc', '-s', "myservice"], {:override_locale => false, :squelch => true, :failonfail => true}) @provider.start end it "should execute the stopsrc command" do - @provider.expects(:execute).with(['/usr/bin/stopsrc', '-s', "myservice"], {:squelch => true, :failonfail => true}) + @provider.expects(:execute).with(['/usr/bin/stopsrc', '-s', "myservice"], {:override_locale => false, :squelch => true, :failonfail => true}) @provider.stop end @@ -90,8 +90,8 @@ _EOF_ myservice::--no-daemonize:/usr/sbin/puppetd:0:0:/dev/null:/var/log/puppet.log:/var/log/puppet.log:-O:-Q:-S:0:0:20:15:9:-d:20::" _EOF_ @provider.expects(:execute).with(['/usr/bin/lssrc', '-Ss', "myservice"]).returns sample_output - @provider.expects(:execute).with(['/usr/bin/stopsrc', '-s', "myservice"], {:squelch => true, :failonfail => true}) - @provider.expects(:execute).with(['/usr/bin/startsrc', '-s', "myservice"], {:squelch => true, :failonfail => true}) + @provider.expects(:execute).with(['/usr/bin/stopsrc', '-s', "myservice"], {:override_locale => false, :squelch => true, :failonfail => true}) + @provider.expects(:execute).with(['/usr/bin/startsrc', '-s', "myservice"], {:override_locale => false, :squelch => true, :failonfail => true}) @provider.restart end end diff --git a/spec/unit/provider/service/systemd_spec.rb b/spec/unit/provider/service/systemd_spec.rb index 38294d86d..5041c56a9 100755 --- a/spec/unit/provider/service/systemd_spec.rb +++ b/spec/unit/provider/service/systemd_spec.rb @@ -17,14 +17,6 @@ describe provider_class do @provider.resource = @resource end - osfamily = [ 'redhat', 'suse' ] - - osfamily.each do |osfamily| - it "should be the default provider on #{osfamily}" do - pending "This test is pending the change in RedHat-related Linuxes to systemd for service management" - end - end - [:enabled?, :enable, :disable, :start, :stop, :status, :restart].each do |method| it "should have a #{method} method" do @provider.should respond_to(method) diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index dfbfe68b2..86ab266f4 100755 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -119,7 +119,7 @@ describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features. resource[:restart] = 'c:/bin/foo' provider.expects(:execute).never - provider.expects(:execute).with(['c:/bin/foo'], :failonfail => true, :squelch => true) + provider.expects(:execute).with(['c:/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true) provider.restart end diff --git a/spec/unit/provider/user/hpux_spec.rb b/spec/unit/provider/user/hpux_spec.rb index f20da4b39..4001b6695 100755 --- a/spec/unit/provider/user/hpux_spec.rb +++ b/spec/unit/provider/user/hpux_spec.rb @@ -1,24 +1,52 @@ -#! /usr/bin/env ruby +#!/usr/bin/env ruby require 'spec_helper' +require 'etc' provider_class = Puppet::Type.type(:user).provider(:hpuxuseradd) describe provider_class do - # left from the useradd test... I have no clue what I'm doing. - before do - @resource = stub("resource", :name => "myuser", :managehome? => nil, :should => "fakeval", :[] => "fakeval") - @provider = provider_class.new(@resource) + let :resource do + Puppet::Type.type(:user).new( + :title => 'testuser', + :comment => 'Test J. User', + :provider => :hpuxuseradd + ) end + let(:provider) { resource.provider } it "should add -F when modifying a user" do - @resource.expects(:allowdupe?).returns true - @provider.expects(:execute).with { |args| args.include?("-F") } - @provider.uid = 1000 + resource.stubs(:allowdupe?).returns true + provider.expects(:execute).with { |args| args.include?("-F") } + provider.uid = 1000 end it "should add -F when deleting a user" do - @provider.stubs(:exists?).returns(true) - @provider.expects(:execute).with { |args| args.include?("-F") } - @provider.delete + provider.stubs(:exists?).returns(true) + provider.expects(:execute).with { |args| args.include?("-F") } + provider.delete + end + + context "managing passwords" do + let :pwent do + Struct::Passwd.new("testuser", "foopassword") + end + + before :each do + Etc.stubs(:getpwent).returns(pwent) + Etc.stubs(:getpwnam).returns(pwent) + end + + it "should have feature manages_passwords" do + provider_class.should be_manages_passwords + end + + it "should return nil if user does not exist" do + Etc.stubs(:getpwent).returns(nil) + provider.password.must be_nil + end + + it "should return password entry if exists" do + provider.password.must == "foopassword" + end end end diff --git a/spec/unit/provider/user/useradd_spec.rb b/spec/unit/provider/user/useradd_spec.rb index 254a2cc8b..d11d4f767 100755 --- a/spec/unit/provider/user/useradd_spec.rb +++ b/spec/unit/provider/user/useradd_spec.rb @@ -25,7 +25,7 @@ describe Puppet::Type.type(:user).provider(:useradd) do it "should add -o when allowdupe is enabled and the user is being created" do resource[:allowdupe] = true - provider.expects(:execute).with(['/usr/sbin/useradd', '-o', 'myuser']) + provider.expects(:execute).with(includes('-o')) provider.create end @@ -33,7 +33,7 @@ describe Puppet::Type.type(:user).provider(:useradd) do it "should add -r when system is enabled" do resource[:system] = :true provider.should be_system_users - provider.expects(:execute).with(['/usr/sbin/useradd', '-r', 'myuser']) + provider.expects(:execute).with(includes('-r')) provider.create end end @@ -51,7 +51,7 @@ describe Puppet::Type.type(:user).provider(:useradd) do described_class.has_feature :manages_password_age resource[:password_min_age] = 5 resource[:password_max_age] = 10 - provider.expects(:execute).with(['/usr/sbin/useradd', 'myuser']) + provider.expects(:execute).with(includes('/usr/sbin/useradd')) provider.expects(:execute).with(['/usr/bin/chage', '-m', 5, '-M', 10, 'myuser']) provider.create end @@ -109,42 +109,35 @@ describe Puppet::Type.type(:user).provider(:useradd) do end describe "#check_manage_home" do - it "should check manage home" do - resource.expects(:managehome?) - provider.check_manage_home - end - it "should return an array with -m flag if home is managed" do resource[:managehome] = :true - provider.check_manage_home.must == ["-m"] + provider.expects(:execute).with(includes('-m')) + provider.create end it "should return an array with -r flag if home is managed" do resource[:managehome] = :true resource[:ensure] = :absent - provider.deletecmd.must == ['/usr/sbin/userdel', '-r', 'myuser'] + provider.stubs(:exists?).returns(true) + provider.expects(:execute).with(includes('-r')) + provider.delete end - it "should return an array with -M if home is not managed and on Redhat" do - Facter.stubs(:value).with(:operatingsystem).returns("RedHat") + it "should use -M flag if home is not managed and on Redhat" do + Facter.stubs(:value).with(:osfamily).returns("RedHat") resource[:managehome] = :false - provider.check_manage_home.must == ["-M"] + provider.expects(:execute).with(includes('-M')) + provider.create end - it "should return an empty array if home is not managed and not on Redhat" do - Facter.stubs(:value).with(:operatingsystem).returns("some OS") + it "should not use -M flag if home is not managed and not on Redhat" do + Facter.stubs(:value).with(:osfamily).returns("not RedHat") resource[:managehome] = :false - provider.check_manage_home.must == [] + provider.expects(:execute).with(Not(includes('-M'))) + provider.create end end - describe "when adding properties" do - it "should get the valid properties" - it "should not add the ensure property" - it "should add the flag and value to an array" - it "should return and array of flags and values" - end - describe "#addcmd" do before do resource[:allowdupe] = :true diff --git a/spec/unit/relationship_spec.rb b/spec/unit/relationship_spec.rb index 01e863ff1..a6aeffc4f 100755 --- a/spec/unit/relationship_spec.rb +++ b/spec/unit/relationship_spec.rb @@ -151,7 +151,7 @@ describe Puppet::Relationship, " when matching edges with a non-standard event" end end -describe Puppet::Relationship, "when converting to pson", :if => Puppet.features.pson? do +describe Puppet::Relationship, "when converting to pson" do before do @edge = Puppet::Relationship.new(:a, :b, :event => :random, :callback => :whatever) end @@ -184,7 +184,7 @@ describe Puppet::Relationship, "when converting to pson", :if => Puppet.features end end -describe Puppet::Relationship, "when converting from pson", :if => Puppet.features.pson? do +describe Puppet::Relationship, "when converting from pson" do before do @event = "random" @callback = "whatever" diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb index aa84107ae..52673c726 100755 --- a/spec/unit/resource/catalog_spec.rb +++ b/spec/unit/resource/catalog_spec.rb @@ -775,7 +775,7 @@ describe Puppet::Resource::Catalog, "when compiling" do end end -describe Puppet::Resource::Catalog, "when converting to pson", :if => Puppet.features.pson? do +describe Puppet::Resource::Catalog, "when converting to pson" do before do @catalog = Puppet::Resource::Catalog.new("myhost") end @@ -833,7 +833,7 @@ describe Puppet::Resource::Catalog, "when converting to pson", :if => Puppet.fea end end -describe Puppet::Resource::Catalog, "when converting from pson", :if => Puppet.features.pson? do +describe Puppet::Resource::Catalog, "when converting from pson" do def pson_result_should Puppet::Resource::Catalog.expects(:new).with { |hash| yield hash } end diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb index a682a7b48..e80e903d8 100755 --- a/spec/unit/resource/type_spec.rb +++ b/spec/unit/resource/type_spec.rb @@ -150,24 +150,6 @@ describe Puppet::Resource::Type do Puppet::Resource::Type.new(:node, "fOo").match("foO").should be_true end end - - it "should return the name converted to a string when the name is not a regex" do - pending "Need to define LoadedCode behaviour first" - name = Puppet::Parser::AST::HostName.new(:value => "foo") - Puppet::Resource::Type.new(:node, name).name.should == "foo" - end - - it "should return the name converted to a string when the name is a regex" do - pending "Need to define LoadedCode behaviour first" - name = Puppet::Parser::AST::HostName.new(:value => /regex/) - Puppet::Resource::Type.new(:node, name).name.should == /regex/.to_s - end - - it "should mark any created scopes as a node scope" do - pending "Need to define LoadedCode behaviour first" - name = Puppet::Parser::AST::HostName.new(:value => /regex/) - Puppet::Resource::Type.new(:node, name).name.should == /regex/.to_s - end end describe "when initializing" do diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index dab9c2b82..4ce718758 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -647,7 +647,7 @@ type: File end end - describe "when converting to pson", :if => Puppet.features.pson? do + describe "when converting to pson" do def pson_output_should @resource.class.expects(:pson_create).with { |hash| yield hash } end @@ -726,7 +726,7 @@ type: File end end - describe "when converting from pson", :if => Puppet.features.pson? do + describe "when converting from pson" do def pson_result_should Puppet::Resource.expects(:new).with { |hash| yield hash } end diff --git a/spec/unit/settings/config_file_spec.rb b/spec/unit/settings/config_file_spec.rb new file mode 100644 index 000000000..0d3112097 --- /dev/null +++ b/spec/unit/settings/config_file_spec.rb @@ -0,0 +1,100 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' +require 'puppet/settings/config_file' + +describe Puppet::Settings::ConfigFile do + NOTHING = {} + + def section_containing(data) + meta = data[:meta] || {} + values = data.reject { |key, _| key == :meta } + values.merge({ :_meta => Hash[values.keys.collect { |key| [key, meta[key] || {}] }] }) + end + + def the_parse_of(*lines) + config.parse_file(filename, lines.join("\n")) + end + + let(:identity_transformer) { Proc.new { |value| value } } + let(:config) { Puppet::Settings::ConfigFile.new(identity_transformer) } + + let(:filename) { "a/fake/filename.conf" } + + it "interprets an empty file to contain a main section with no entries" do + the_parse_of("").should == { :main => section_containing(NOTHING) } + end + + it "interprets an empty main section the same as an empty file" do + the_parse_of("").should == config.parse_file(filename, "[main]") + end + + it "places an entry in no section in main" do + the_parse_of("var = value").should == { :main => section_containing(:var => "value") } + end + + it "places an entry after a section header in that section" do + the_parse_of("[section]", "var = value").should == { :main => section_containing(NOTHING), + :section => section_containing(:var => "value") } + end + + it "does not include trailing whitespace in the value" do + the_parse_of("var = value\t ").should == { :main => section_containing(:var => "value") } + end + + it "does not include leading whitespace in the name" do + the_parse_of(" \t var=value").should == { :main => section_containing(:var => "value") } + end + + it "skips lines that are commented out" do + the_parse_of("#var = value").should == { :main => section_containing(NOTHING) } + end + + it "skips lines that are entirely whitespace" do + the_parse_of(" \t ").should == { :main => section_containing(NOTHING) } + end + + it "errors when a line is not a known form" do + expect { the_parse_of("unknown") }.to raise_error Puppet::Settings::ParseError, /Could not match line/ + end + + it "stores file meta information in the _meta section" do + the_parse_of("var = value { owner = me, group = you, mode = 0666 }").should == + { :main => section_containing(:var => "value", :meta => { :var => { :owner => "me", + :group => "you", + :mode => "0666" } }) } + end + + it "errors when there is unknown meta information" do + expect { the_parse_of("var = value { unknown = no }") }. + to raise_error ArgumentError, /Invalid file option 'unknown'/ + end + + it "errors when the mode is not numeric" do + expect { the_parse_of("var = value { mode = no }") }. + to raise_error ArgumentError, "File modes must be numbers" + end + + it "errors when the options are not key-value pairs" do + expect { the_parse_of("var = value { mode }") }. + to raise_error ArgumentError, "Could not parse 'value { mode }'" + end + + it "errors when an application_defaults section is created" do + expect { the_parse_of("[application_defaults]") }. + to raise_error Puppet::Error, + "Illegal section 'application_defaults' in config file #{filename} at line [application_defaults]" + end + + it "transforms values with the given function" do + config = Puppet::Settings::ConfigFile.new(Proc.new { |value| value + " changed" }) + + config.parse_file(filename, "var = value").should == { :main => section_containing(:var => "value changed") } + end + + it "does not try to transform an entry named 'mode'" do + config = Puppet::Settings::ConfigFile.new(Proc.new { raise "Should not transform" }) + + config.parse_file(filename, "mode = value").should == { :main => section_containing(:mode => "value") } + end +end + diff --git a/spec/unit/settings/file_setting_spec.rb b/spec/unit/settings/file_setting_spec.rb index 63564032c..33915ccd4 100755 --- a/spec/unit/settings/file_setting_spec.rb +++ b/spec/unit/settings/file_setting_spec.rb @@ -9,111 +9,113 @@ describe Puppet::Settings::FileSetting do include PuppetSpec::Files - before do - @basepath = make_absolute("/somepath") - end + describe "when controlling permissions" do + def settings(wanted_values = {}) + real_values = { + :user => 'root', + :group => 'root', + :mkusers => false, + :service_user_available? => false, + :service_group_available? => false + }.merge(wanted_values) - describe "when determining whether the service user should be used" do - before do - @settings = mock 'settings' - @settings.stubs(:[]).with(:mkusers).returns false - @settings.stubs(:service_user_available?).returns true - end + settings = mock("settings") - it "should be true if the service user is available" do - @settings.expects(:service_user_available?).returns true - setting = FileSetting.new(:settings => @settings, :owner => "root", :desc => "a setting") - setting.should be_use_service_user - end + settings.stubs(:[]).with(:user).returns real_values[:user] + settings.stubs(:[]).with(:group).returns real_values[:group] + settings.stubs(:[]).with(:mkusers).returns real_values[:mkusers] + settings.stubs(:service_user_available?).returns real_values[:service_user_available?] + settings.stubs(:service_group_available?).returns real_values[:service_group_available?] - it "should be true if 'mkusers' is set" do - @settings.expects(:[]).with(:mkusers).returns true - setting = FileSetting.new(:settings => @settings, :owner => "root", :desc => "a setting") - setting.should be_use_service_user + settings end - it "should be false if the service user is not available and 'mkusers' is unset" do - setting = FileSetting.new(:settings => @settings, :owner => "root", :desc => "a setting") - setting.should be_use_service_user - end - end + context "owner" do + it "can always be root" do + settings = settings(:user => "the_service", :mkusers => true) - describe "when setting the owner" do - it "should allow the file to be owned by root" do - root_owner = lambda { FileSetting.new(:settings => mock("settings"), :owner => "root", :desc => "a setting") } - root_owner.should_not raise_error - end + setting = FileSetting.new(:settings => settings, :owner => "root", :desc => "a setting") - it "should allow the file to be owned by the service user" do - service_owner = lambda { FileSetting.new(:settings => mock("settings"), :owner => "service", :desc => "a setting") } - service_owner.should_not raise_error - end + setting.owner.should == "root" + end - it "should allow the ownership of the file to be unspecified" do - no_owner = lambda { FileSetting.new(:settings => mock("settings"), :desc => "a setting") } - no_owner.should_not raise_error - end + it "is the service user if we are making users" do + settings = settings(:user => "the_service", :mkusers => true, :service_user_available? => false) - it "should not allow other owners" do - invalid_owner = lambda { FileSetting.new(:settings => mock("settings"), :owner => "invalid", :desc => "a setting") } - invalid_owner.should raise_error(FileSetting::SettingError) - end - end + setting = FileSetting.new(:settings => settings, :owner => "service", :desc => "a setting") - describe "when reading the owner" do - it "should be root when the setting specifies root" do - setting = FileSetting.new(:settings => mock("settings"), :owner => "root", :desc => "a setting") - setting.owner.should == "root" - end + setting.owner.should == "the_service" + end - it "should be the owner of the service when the setting specifies service and the service user should be used" do - settings = mock("settings") - settings.stubs(:[]).returns "the_service" + it "is the service user if the user is available on the system" do + settings = settings(:user => "the_service", :mkusers => false, :service_user_available? => true) - setting = FileSetting.new(:settings => settings, :owner => "service", :desc => "a setting") - setting.expects(:use_service_user?).returns true - setting.owner.should == "the_service" - end + setting = FileSetting.new(:settings => settings, :owner => "service", :desc => "a setting") - it "should be the root when the setting specifies service and the service user should not be used" do - settings = mock("settings") - settings.stubs(:[]).returns "the_service" + setting.owner.should == "the_service" + end - setting = FileSetting.new(:settings => settings, :owner => "service", :desc => "a setting") - setting.expects(:use_service_user?).returns false - setting.owner.should == "root" - end + it "is root when the setting specifies service and the user is not available on the system" do + settings = settings(:user => "the_service", :mkusers => false, :service_user_available? => false) - it "should be nil when the owner is unspecified" do - FileSetting.new(:settings => mock("settings"), :desc => "a setting").owner.should be_nil - end - end + setting = FileSetting.new(:settings => settings, :owner => "service", :desc => "a setting") - describe "when setting the group" do - it "should allow the group to be service" do - service_group = lambda { FileSetting.new(:settings => mock("settings"), :group => "service", :desc => "a setting") } - service_group.should_not raise_error - end + setting.owner.should == "root" + end - it "should allow the group to be unspecified" do - no_group = lambda { FileSetting.new(:settings => mock("settings"), :desc => "a setting") } - no_group.should_not raise_error - end + it "is unspecified when no specific owner is wanted" do + FileSetting.new(:settings => settings(), :desc => "a setting").owner.should be_nil + end - it "should not allow invalid groups" do - invalid_group = lambda { FileSetting.new(:settings => mock("settings"), :group => "invalid", :desc => "a setting") } - invalid_group.should raise_error(FileSetting::SettingError) + it "does not allow other owners" do + expect { FileSetting.new(:settings => settings(), :desc => "a setting", :name => "testing", :default => "the default", :owner => "invalid") }. + to raise_error(FileSetting::SettingError, /The :owner parameter for the setting 'testing' must be either 'root' or 'service'/) + end end - end - describe "when reading the group" do - it "should be service when the setting specifies service" do - setting = FileSetting.new(:settings => mock("settings", :[] => "the_service"), :group => "service", :desc => "a setting") - setting.group.should == "the_service" - end + context "group" do + it "is unspecified when no specific group is wanted" do + setting = FileSetting.new(:settings => settings(), :desc => "a setting") + + setting.group.should be_nil + end + + it "is root if root is requested" do + settings = settings(:group => "the_group") + + setting = FileSetting.new(:settings => settings, :group => "root", :desc => "a setting") + + setting.group.should == "root" + end + + it "is the service group if we are making users" do + settings = settings(:group => "the_service", :mkusers => true) - it "should be nil when the group is unspecified" do - FileSetting.new(:settings => mock("settings"), :desc => "a setting").group.should be_nil + setting = FileSetting.new(:settings => settings, :group => "service", :desc => "a setting") + + setting.group.should == "the_service" + end + + it "is the service user if the group is available on the system" do + settings = settings(:group => "the_service", :mkusers => false, :service_group_available? => true) + + setting = FileSetting.new(:settings => settings, :group => "service", :desc => "a setting") + + setting.group.should == "the_service" + end + + it "is unspecified when the setting specifies service and the group is not available on the system" do + settings = settings(:group => "the_service", :mkusers => false, :service_group_available? => false) + + setting = FileSetting.new(:settings => settings, :group => "service", :desc => "a setting") + + setting.group.should be_nil + end + + it "does not allow other groups" do + expect { FileSetting.new(:settings => settings(), :group => "invalid", :name => 'testing', :desc => "a setting") }. + to raise_error(FileSetting::SettingError, /The :group parameter for the setting 'testing' must be either 'root' or 'service'/) + end end end @@ -123,6 +125,7 @@ describe Puppet::Settings::FileSetting do describe "when being converted to a resource" do before do + @basepath = make_absolute("/somepath") @settings = mock 'settings' @file = Puppet::Settings::FileSetting.new(:settings => @settings, :desc => "eh", :name => :myfile, :section => "mysect") @file.stubs(:create_files?).returns true diff --git a/spec/unit/settings/value_translator_spec.rb b/spec/unit/settings/value_translator_spec.rb new file mode 100644 index 000000000..a318f6d48 --- /dev/null +++ b/spec/unit/settings/value_translator_spec.rb @@ -0,0 +1,77 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' +require 'puppet/settings/value_translator' + +describe Puppet::Settings::ValueTranslator do + let(:translator) { Puppet::Settings::ValueTranslator.new } + + context "booleans" do + it "translates strings representing booleans to booleans" do + translator['true'].should == true + translator['false'].should == false + end + + it "translates boolean values into themselves" do + translator[true].should == true + translator[false].should == false + end + + it "leaves a boolean string with whitespace as a string" do + translator[' true'].should == " true" + translator['true '].should == "true" + + translator[' false'].should == " false" + translator['false '].should == "false" + end + end + + context "numbers" do + it "translates integer strings to integers" do + translator["1"].should == 1 + translator["2"].should == 2 + end + + it "translates numbers starting with a 0 as octal" do + translator["011"].should == 9 + end + + it "leaves hex numbers as strings" do + translator["0x11"].should == "0x11" + end + end + + context "arbitrary strings" do + it "translates an empty string as the empty string" do + translator[""].should == "" + end + + + it "strips double quotes" do + translator['"a string"'].should == 'a string' + end + + it "strips single quotes" do + translator["'a string'"].should == "a string" + end + + it "does not strip preceeding whitespace" do + translator[" \ta string"].should == " \ta string" + end + + it "strips trailing whitespace" do + translator["a string\t "].should == "a string" + end + + it "leaves leading quote that is preceeded by whitespace" do + translator[" 'a string'"].should == " 'a string" + end + + it "leaves trailing quote that is succeeded by whitespace" do + translator["'a string' "].should == "a string'" + end + + it "leaves quotes that are not at the beginning or end of the string" do + translator["a st'\"ring"].should == "a st'\"ring" + end + end +end diff --git a/spec/unit/settings_spec.rb b/spec/unit/settings_spec.rb index b2196bed6..42013ac64 100755 --- a/spec/unit/settings_spec.rb +++ b/spec/unit/settings_spec.rb @@ -85,14 +85,6 @@ describe Puppet::Settings do @settings.define_settings(:main, PuppetSpec::Settings::TEST_APP_DEFAULT_DEFINITIONS) end - it "should fail if someone attempts to initialize app defaults more than once" do - @settings.initialize_app_defaults(default_values) - - expect { - @settings.initialize_app_defaults(default_values) - }.to raise_error(Puppet::DevError) - end - it "should fail if the app defaults hash is missing any required values" do incomplete_default_values = default_values.reject { |key, _| key == :confdir } expect { @@ -676,6 +668,7 @@ describe Puppet::Settings do before do @settings = Puppet::Settings.new @settings.stubs(:service_user_available?).returns true + @settings.stubs(:service_group_available?).returns true @file = make_absolute("/some/file") @userconfig = make_absolute("/test/userconfigfile") @settings.define_settings :section, :user => { :default => "suser", :desc => "doc" }, :group => { :default => "sgroup", :desc => "doc" } @@ -785,6 +778,33 @@ describe Puppet::Settings do @settings.metadata(:myfile).should == {:owner => "suser"} end + it "should support loading metadata (owner, group, or mode) from a run_mode section in the configuration file" do + default_values = {} + PuppetSpec::Settings::TEST_APP_DEFAULT_DEFINITIONS.keys.each do |key| + default_values[key] = 'default value' + end + @settings.define_settings :main, PuppetSpec::Settings::TEST_APP_DEFAULT_DEFINITIONS + @settings.define_settings :master, :myfile => { :type => :file, :default => make_absolute("/myfile"), :desc => "a" } + + otherfile = make_absolute("/other/file") + text = "[master] + myfile = #{otherfile} {mode = 664} + " + @settings.expects(:read_file).returns(text) + + # will start initialization as user + @settings.preferred_run_mode.should == :user + @settings.send(:parse_config_files) + + # change app run_mode to master + @settings.initialize_app_defaults(default_values.merge(:run_mode => :master)) + @settings.preferred_run_mode.should == :master + + # initializing the app should have reloaded the metadata based on run_mode + @settings[:myfile].should == otherfile + @settings.metadata(:myfile).should == {:mode => "664"} + end + it "should call hooks associated with values set in the configuration file" do values = [] @settings.define_settings :section, :mysetting => {:default => "defval", :desc => "a", :hook => proc { |v| values << v }} @@ -1245,6 +1265,7 @@ describe Puppet::Settings do before do @settings = Puppet::Settings.new @settings.stubs(:service_user_available?).returns true + @settings.stubs(:service_group_available?).returns true @settings.define_settings :main, :noop => { :default => false, :desc => "", :type => :boolean } @settings.define_settings :main, :maindir => { :type => :directory, :default => make_absolute("/maindir"), :desc => "a" }, @@ -1282,12 +1303,6 @@ describe Puppet::Settings do @settings.use(:main, :other) end - it "should ignore tags and schedules when creating files and directories" - - it "should be able to provide all of its parameters in a format compatible with GetOpt::Long" do - pending "Not converted from test/unit yet" - end - it "should convert the created catalog to a RAL catalog" do @catalog = Puppet::Resource::Catalog.new("foo") @settings.expects(:to_catalog).with(:main).returns @catalog @@ -1403,8 +1418,6 @@ describe Puppet::Settings do @settings.print_configs end - it "should print a whole bunch of stuff if :configprint = all" - it "should return true after printing" do @settings.stubs(:value).with(:configprint).returns("something") @settings.stubs(:include?).with("something").returns(true) @@ -1460,35 +1473,89 @@ describe Puppet::Settings do end describe "when determining if the service user is available" do + let(:settings) do + settings = Puppet::Settings.new + settings.define_settings :main, :user => { :default => nil, :desc => "doc" } + settings + end + + def a_user_type_for(username) + user = mock 'user' + Puppet::Type.type(:user).expects(:new).with { |args| args[:name] == username }.returns user + user + end + it "should return false if there is no user setting" do - Puppet::Settings.new.should_not be_service_user_available + settings.should_not be_service_user_available end it "should return false if the user provider says the user is missing" do - settings = Puppet::Settings.new - settings.define_settings :main, :user => { :default => "foo", :desc => "doc" } - - user = mock 'user' - user.expects(:exists?).returns false + settings[:user] = "foo" - Puppet::Type.type(:user).expects(:new).with { |args| args[:name] == "foo" }.returns user + a_user_type_for("foo").expects(:exists?).returns false settings.should_not be_service_user_available end it "should return true if the user provider says the user is present" do - settings = Puppet::Settings.new - settings.define_settings :main, :user => { :default => "foo", :desc => "doc" } + settings[:user] = "foo" - user = mock 'user' - user.expects(:exists?).returns true + a_user_type_for("foo").expects(:exists?).returns true - Puppet::Type.type(:user).expects(:new).with { |args| args[:name] == "foo" }.returns user + settings.should be_service_user_available + end + + it "caches the result of determining if the user is present" do + settings[:user] = "foo" + + a_user_type_for("foo").expects(:exists?).returns true + settings.should be_service_user_available settings.should be_service_user_available end + end + + describe "when determining if the service group is available" do + let(:settings) do + settings = Puppet::Settings.new + settings.define_settings :main, :group => { :default => nil, :desc => "doc" } + settings + end - it "should cache the result" + def a_group_type_for(groupname) + group = mock 'group' + Puppet::Type.type(:group).expects(:new).with { |args| args[:name] == groupname }.returns group + group + end + + it "should return false if there is no group setting" do + settings.should_not be_service_group_available + end + + it "should return false if the group provider says the group is missing" do + settings[:group] = "foo" + + a_group_type_for("foo").expects(:exists?).returns false + + settings.should_not be_service_group_available + end + + it "should return true if the group provider says the group is present" do + settings[:group] = "foo" + + a_group_type_for("foo").expects(:exists?).returns true + + settings.should be_service_group_available + end + + it "caches the result of determining if the group is present" do + settings[:group] = "foo" + + a_group_type_for("foo").expects(:exists?).returns true + settings.should be_service_group_available + + settings.should be_service_group_available + end end describe "#writesub" do diff --git a/spec/unit/ssl/certificate_request_spec.rb b/spec/unit/ssl/certificate_request_spec.rb index 8b804d58b..b6d07c695 100755 --- a/spec/unit/ssl/certificate_request_spec.rb +++ b/spec/unit/ssl/certificate_request_spec.rb @@ -211,6 +211,24 @@ describe Puppet::SSL::CertificateRequest do generated.should be_a(OpenSSL::X509::Request) generated.should be(request.content) end + + it "should use SHA1 to sign the csr when SHA256 isn't available" do + csr = OpenSSL::X509::Request.new + OpenSSL::Digest.expects(:const_defined?).with("SHA256").returns(false) + OpenSSL::Digest.expects(:const_defined?).with("SHA1").returns(true) + signer = Puppet::SSL::CertificateSigner.new + signer.sign(csr, key.content) + csr.verify(key.content).should be_true + end + + it "should raise an error if neither SHA256 nor SHA1 are available" do + csr = OpenSSL::X509::Request.new + OpenSSL::Digest.expects(:const_defined?).with("SHA256").returns(false) + OpenSSL::Digest.expects(:const_defined?).with("SHA1").returns(false) + expect { + signer = Puppet::SSL::CertificateSigner.new + }.to raise_error(Puppet::Error) + end end describe "when a CSR is saved" do diff --git a/spec/unit/type/file/ensure_spec.rb b/spec/unit/type/file/ensure_spec.rb index 44cb3e025..310558ff8 100755 --- a/spec/unit/type/file/ensure_spec.rb +++ b/spec/unit/type/file/ensure_spec.rb @@ -1,84 +1,123 @@ #! /usr/bin/env ruby require 'spec_helper' +require 'puppet/type/file/ensure' -property = Puppet::Type.type(:file).attrclass(:ensure) +describe Puppet::Type::File::Ensure do + include PuppetSpec::Files -describe property do - before do - # Wow that's a messy interface to the resource. - @resource = stub 'resource', :[] => nil, :[]= => nil, :property => nil, :newattr => nil, :parameter => nil, :replace? => true - @resource.stubs(:[]).returns "foo" - @resource.stubs(:[]).with(:path).returns "/my/file" - @ensure = property.new :resource => @resource - end + let(:path) { tmpfile('file_ensure') } + let(:resource) { Puppet::Type.type(:file).new(:ensure => 'file', :path => path, :replace => true) } + let(:property) { resource.property(:ensure) } it "should be a subclass of Ensure" do - property.superclass.must == Puppet::Property::Ensure + described_class.superclass.must == Puppet::Property::Ensure end describe "when retrieving the current state" do it "should return :absent if the file does not exist" do - @ensure = property.new(:resource => @resource) - @resource.expects(:stat).returns nil + resource.expects(:stat).returns nil - @ensure.retrieve.should == :absent + property.retrieve.should == :absent end it "should return the current file type if the file exists" do - @ensure = property.new(:resource => @resource) stat = mock 'stat', :ftype => "directory" - @resource.expects(:stat).returns stat + resource.expects(:stat).returns stat - @ensure.retrieve.should == :directory + property.retrieve.should == :directory end end describe "when testing whether :ensure is in sync" do - before do - @ensure = property.new(:resource => @resource) - @stat = stub 'stat', :ftype => "file" - end - it "should always be in sync if replace is 'false' unless the file is missing" do - @ensure.should = :file - @resource.expects(:replace?).returns false - @ensure.safe_insync?(:link).should be_true + property.should = :file + resource.expects(:replace?).returns false + property.safe_insync?(:link).should be_true end it "should be in sync if :ensure is set to :absent and the file does not exist" do - @ensure.should = :absent + property.should = :absent - @ensure.must be_safe_insync(:absent) + property.must be_safe_insync(:absent) end it "should not be in sync if :ensure is set to :absent and the file exists" do - @ensure.should = :absent + property.should = :absent - @ensure.should_not be_safe_insync(:file) + property.should_not be_safe_insync(:file) end it "should be in sync if a normal file exists and :ensure is set to :present" do - @ensure.should = :present + property.should = :present - @ensure.must be_safe_insync(:file) + property.must be_safe_insync(:file) end it "should be in sync if a directory exists and :ensure is set to :present" do - @ensure.should = :present + property.should = :present - @ensure.must be_safe_insync(:directory) + property.must be_safe_insync(:directory) end it "should be in sync if a symlink exists and :ensure is set to :present" do - @ensure.should = :present + property.should = :present - @ensure.must be_safe_insync(:link) + property.must be_safe_insync(:link) end it "should not be in sync if :ensure is set to :file and a directory exists" do - @ensure.should = :file + property.should = :file + + property.should_not be_safe_insync(:directory) + end + end + + describe "#sync" do + context "directory" do + before :each do + resource[:ensure] = :directory + end + + it "should raise if the parent directory doesn't exist" do + newpath = File.join(path, 'nonexistentparent', 'newdir') + resource[:path] = newpath + + expect { + property.sync + }.to raise_error(Puppet::Error, /Cannot create #{newpath}; parent directory #{File.dirname(newpath)} does not exist/) + end + + it "should accept octal mode as fixnum" do + resource[:mode] = 0700 + resource.expects(:property_fix) + Dir.expects(:mkdir).with(path, 0700) + + property.sync + end + + it "should accept octal mode as string" do + resource[:mode] = "700" + resource.expects(:property_fix) + Dir.expects(:mkdir).with(path, 0700) + + property.sync + end + + it "should accept octal mode as string with leading zero" do + resource[:mode] = "0700" + resource.expects(:property_fix) + Dir.expects(:mkdir).with(path, 0700) + + property.sync + end + + it "should accept symbolic mode" do + resource[:mode] = "u=rwx,go=x" + resource.expects(:property_fix) + Dir.expects(:mkdir).with(path, 0711) - @ensure.should_not be_safe_insync(:directory) + property.sync + end end end end diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb index b910cf87b..d71c041a8 100755 --- a/spec/unit/type/file_spec.rb +++ b/spec/unit/type/file_spec.rb @@ -194,32 +194,6 @@ describe Puppet::Type.type(:file) do end end - describe "#asuser" do - before :each do - # Mocha won't let me just stub SUIDManager.asuser to yield and return, - # but it will do exactly that if we're not root. - Puppet.features.stubs(:root?).returns false - end - - it "should return the desired owner if they can write to the parent directory" do - file[:owner] = 1001 - FileTest.stubs(:writable?).with(File.dirname file[:path]).returns true - - file.asuser.should == 1001 - end - - it "should return nil if the desired owner can't write to the parent directory" do - file[:owner] = 1001 - FileTest.stubs(:writable?).with(File.dirname file[:path]).returns false - - file.asuser.should == nil - end - - it "should return nil if not managing owner" do - file.asuser.should == nil - end - end - describe "#bucket" do it "should return nil if backup is off" do file[:backup] = false @@ -288,48 +262,6 @@ describe Puppet::Type.type(:file) do end end - describe "#bucket" do - it "should return nil if backup is off" do - file[:backup] = false - file.bucket.should == nil - end - - it "should return nil if using a file extension for backup" do - file[:backup] = '.backup' - - file.bucket.should == nil - end - - it "should return the default filebucket if using the 'puppet' filebucket" do - file[:backup] = 'puppet' - bucket = stub('bucket') - file.stubs(:default_bucket).returns bucket - - file.bucket.should == bucket - end - - it "should fail if using a remote filebucket and no catalog exists" do - file.catalog = nil - file[:backup] = 'my_bucket' - - expect { file.bucket }.to raise_error(Puppet::Error, "Can not find filebucket for backups without a catalog") - end - - it "should fail if the specified filebucket isn't in the catalog" do - file[:backup] = 'my_bucket' - - expect { file.bucket }.to raise_error(Puppet::Error, "Could not find filebucket my_bucket specified in backup") - end - - it "should use the specified filebucket if it is in the catalog" do - file[:backup] = 'my_bucket' - filebucket = Puppet::Type.type(:filebucket).new(:name => 'my_bucket') - catalog.add_resource(filebucket) - - file.bucket.should == filebucket.bucket - end - end - describe "#exist?" do it "should be considered existent if it can be stat'ed" do file.expects(:stat).returns mock('stat') diff --git a/spec/unit/type/group_spec.rb b/spec/unit/type/group_spec.rb index c87249e90..f8d24f0df 100755 --- a/spec/unit/type/group_spec.rb +++ b/spec/unit/type/group_spec.rb @@ -51,4 +51,14 @@ describe Puppet::Type.type(:group) do group.provider.expects(:delete) group.parameter(:ensure).sync end + + it "delegates the existance check to its provider" do + provider = @class.provide(:testing) {} + provider_instance = provider.new + provider_instance.expects(:exists?).returns true + + type = @class.new(:name => "group", :provider => provider_instance) + + type.exists?.should == true + end end diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb index f9a57df1e..933855914 100755 --- a/spec/unit/util/autoload_spec.rb +++ b/spec/unit/util/autoload_spec.rb @@ -262,4 +262,10 @@ describe Puppet::Util::Autoload do end end end + + describe "#expand" do + it "should expand relative to the autoloader's prefix" do + @autoload.expand('bar').should == 'tmp/bar' + end + end end diff --git a/spec/unit/util/command_line_spec.rb b/spec/unit/util/command_line_spec.rb index 809c46636..3d8f896d1 100755 --- a/spec/unit/util/command_line_spec.rb +++ b/spec/unit/util/command_line_spec.rb @@ -6,64 +6,62 @@ require 'puppet/util/command_line' describe Puppet::Util::CommandLine do include PuppetSpec::Files - let :tty do stub("tty", :tty? => true) end - let :pipe do stub("pipe", :tty? => false) end context "#initialize" do it "should pull off the first argument if it looks like a subcommand" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ client --help whatever.pp }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ client --help whatever.pp }) command_line.subcommand_name.should == "client" command_line.args.should == %w{ --help whatever.pp } end it "should return nil if the first argument looks like a .pp file" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.pp }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.pp }) command_line.subcommand_name.should == nil command_line.args.should == %w{ whatever.pp } end it "should return nil if the first argument looks like a .rb file" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.rb }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.rb }) command_line.subcommand_name.should == nil command_line.args.should == %w{ whatever.rb } end it "should return nil if the first argument looks like a flag" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ --debug }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ --debug }) command_line.subcommand_name.should == nil command_line.args.should == %w{ --debug } end it "should return nil if the first argument is -" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ - }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ - }) command_line.subcommand_name.should == nil command_line.args.should == %w{ - } end it "should return nil if the first argument is --help" do - command_line = Puppet::Util::CommandLine.new("puppet", %w{ --help }, tty) + command_line = Puppet::Util::CommandLine.new("puppet", %w{ --help }) command_line.subcommand_name.should == nil end - it "should return nil if there are no arguments on a tty" do - command_line = Puppet::Util::CommandLine.new("puppet", [], tty) + it "should return nil if there are no arguments" do + command_line = Puppet::Util::CommandLine.new("puppet", []) command_line.subcommand_name.should == nil command_line.args.should == [] end - it "should return nil if there are no arguments on a pipe" do - command_line = Puppet::Util::CommandLine.new("puppet", [], pipe) - - command_line.subcommand_name.should == nil - command_line.args.should == [] + it "should pick up changes to the array of arguments" do + args = %w{subcommand} + command_line = Puppet::Util::CommandLine.new("puppet", args) + args[0] = 'different_subcommand' + command_line.subcommand_name.should == 'different_subcommand' end end @@ -71,40 +69,32 @@ describe Puppet::Util::CommandLine do %w{--version -V}.each do |arg| it "should print the version and exit if #{arg} is given" do expect do - described_class.new("puppet", [arg], tty).execute - end.to have_printed(Puppet.version) + described_class.new("puppet", [arg]).execute + end.to have_printed(/^#{Puppet.version}$/) end end end describe "when dealing with puppet commands" do it "should return the executable name if it is not puppet" do - command_line = Puppet::Util::CommandLine.new("puppetmasterd", [], tty) + command_line = Puppet::Util::CommandLine.new("puppetmasterd", []) command_line.subcommand_name.should == "puppetmasterd" end describe "when the subcommand is not implemented" do it "should find and invoke an executable with a hyphenated name" do - commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], tty) + commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument']) Puppet::Util.expects(:which).with('puppet-whatever'). returns('/dev/null/puppet-whatever') - # It is important that we abort at the point exec is called, because - # the code (reasonably) assumes that if `exec` is called processing - # immediately terminates, and we are replaced by the executed process. - # - # This raise isn't a perfect simulation of that, but it is enough to - # validate that the system works, and ... well, if exec is broken we - # have two problems, y'know. - commandline.expects(:exec).with('/dev/null/puppet-whatever', 'argument'). - raises(SystemExit) - - expect { commandline.execute }.to raise_error SystemExit + Kernel.expects(:exec).with('/dev/null/puppet-whatever', 'argument') + + commandline.execute end describe "and an external implementation cannot be found" do it "should abort and show the usage message" do - commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], tty) + commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument']) Puppet::Util.expects(:which).with('puppet-whatever').returns(nil) commandline.expects(:exec).never @@ -112,43 +102,45 @@ describe Puppet::Util::CommandLine do commandline.execute }.to have_printed(/Unknown Puppet subcommand 'whatever'/) end + + it "should abort and show the help message" do + commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument']) + Puppet::Util.expects(:which).with('puppet-whatever').returns(nil) + commandline.expects(:exec).never + + expect { + commandline.execute + }.to have_printed(/See 'puppet help' for help on available puppet subcommands/) + end + + %w{--version -V}.each do |arg| + it "should abort and display #{arg} information" do + commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', arg]) + Puppet::Util.expects(:which).with('puppet-whatever').returns(nil) + commandline.expects(:exec).never + + expect { + commandline.execute + }.to have_printed(/^#{Puppet.version}$/) + end + end end end + describe 'when loading commands' do - let :core_apps do - %w{describe filebucket kick queue resource agent cert apply doc master} - end + it "should deprecate the available_subcommands instance method" do + Puppet::Application.expects(:available_application_names) + Puppet.expects(:deprecation_warning).with("Puppet::Util::CommandLine#available_subcommands is deprecated; please use Puppet::Application.available_application_names instead.") - let :command_line do - Puppet::Util::CommandLine.new("foo", %w{ client --help whatever.pp }, tty) + command_line = Puppet::Util::CommandLine.new("foo", %w{ client --help whatever.pp }) + command_line.available_subcommands end - it "should expose available_subcommands as a class method" do - core_apps.each do |command| - command_line.available_subcommands.should include command - end - end - it 'should be able to find all existing commands' do - core_apps.each do |command| - command_line.available_subcommands.should include command - end - end - describe 'when multiple paths have applications' do - before do - @dir=tmpdir('command_line_plugin_test') - @appdir="#{@dir}/puppet/application" - FileUtils.mkdir_p(@appdir) - FileUtils.touch("#{@appdir}/foo.rb") - $LOAD_PATH.unshift(@dir) # WARNING: MUST MATCH THE AFTER ACTIONS! - end - it 'should be able to find commands from both paths' do - found = command_line.available_subcommands - found.should include 'foo' - core_apps.each { |cmd| found.should include cmd } - end - after do - $LOAD_PATH.shift # WARNING: MUST MATCH THE BEFORE ACTIONS! - end + it "should deprecate the available_subcommands class method" do + Puppet::Application.expects(:available_application_names) + Puppet.expects(:deprecation_warning).with("Puppet::Util::CommandLine.available_subcommands is deprecated; please use Puppet::Application.available_application_names instead.") + + Puppet::Util::CommandLine.available_subcommands end end end diff --git a/spec/unit/util/metric_spec.rb b/spec/unit/util/metric_spec.rb index ea60b7a71..d3b4c929f 100755 --- a/spec/unit/util/metric_spec.rb +++ b/spec/unit/util/metric_spec.rb @@ -83,13 +83,4 @@ describe Puppet::Util::Metric do it "should return nil if the named value cannot be found" do @metric["foo"].should == 0 end - - # LAK: I'm not taking the time to develop these tests right now. - # I expect they should actually be extracted into a separate class - # anyway. - it "should be able to graph metrics using RRDTool" - - it "should be able to create a new RRDTool database" - - it "should be able to store metrics into an RRDTool database" end diff --git a/spec/unit/util/posix_spec.rb b/spec/unit/util/posix_spec.rb index 64dc65ff7..cc5f960ba 100755 --- a/spec/unit/util/posix_spec.rb +++ b/spec/unit/util/posix_spec.rb @@ -248,8 +248,4 @@ describe Puppet::Util::POSIX do it "should be able to iteratively search for posix values" do @posix.should respond_to(:search_posix_field) end - - describe "when searching for posix values iteratively" do - it "should iterate across all of the structs returned by Etc and return the appropriate field from the first matching value" - end end diff --git a/spec/unit/util/rdoc_spec.rb b/spec/unit/util/rdoc_spec.rb index 87d4cd7fb..b13591374 100755 --- a/spec/unit/util/rdoc_spec.rb +++ b/spec/unit/util/rdoc_spec.rb @@ -142,18 +142,6 @@ describe Puppet::Util::RDoc do # any other output must fail Puppet::Util::RDoc.manifestdoc([my_fixture('basic.pp')]) end - - it "should output resource documentation if needed" do - pending "#6634 being fixed" - Puppet.settings[:document_all] = true - byline = sequence('documentation outputs in line order') - Puppet::Util::RDoc.expects(:puts).with("im a class\n").in_sequence(byline) - Puppet::Util::RDoc.expects(:puts).with("im a node\n").in_sequence(byline) - Puppet::Util::RDoc.expects(:puts).with("im a define\n").in_sequence(byline) - Puppet::Util::RDoc.expects(:puts).with("im a resource\n").in_sequence(byline) - # any other output must fail - Puppet::Util::RDoc.manifestdoc([my_fixture('basic.pp')]) - end end end end diff --git a/spec/unit/util/rubygems_spec.rb b/spec/unit/util/rubygems_spec.rb index 85435f83b..8fda3485f 100644 --- a/spec/unit/util/rubygems_spec.rb +++ b/spec/unit/util/rubygems_spec.rb @@ -37,7 +37,7 @@ describe Puppet::Util::RubyGems::Source do before(:each) { described_class.stubs(:source).returns(Puppet::Util::RubyGems::Gems18Source) } it "#directories returns the lib subdirs of Gem::Specification.latest_specs" do - Gem::Specification.expects(:latest_specs).returns([fake_gem]) + Gem::Specification.expects(:latest_specs).with(true).returns([fake_gem]) described_class.new.directories.should == [gem_lib] end diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb index 2b7f14395..ac2bc2977 100755 --- a/spec/unit/util/selinux_spec.rb +++ b/spec/unit/util/selinux_spec.rb @@ -135,7 +135,6 @@ describe Puppet::Util::SELinux do Selinux.stubs(:matchpathcon).with("/root/chuj", 0).returns(-1) self.stubs(:file_lstat).with("/root/chuj").raises(Errno::EACCES, "/root/chuj") - self.expects(:warning).with("Could not stat; Permission denied - /root/chuj") get_selinux_default_context("/root/chuj").should be_nil end @@ -145,7 +144,6 @@ describe Puppet::Util::SELinux do Selinux.stubs(:matchpathcon).with("/root/chuj", 0).returns(-1) self.stubs(:file_lstat).with("/root/chuj").raises(Errno::ENOENT, "/root/chuj") - self.expects(:warning).with("Could not stat; No such file or directory - /root/chuj") get_selinux_default_context("/root/chuj").should be_nil end diff --git a/spec/unit/util/zaml_spec.rb b/spec/unit/util/zaml_spec.rb index 4aa2f1a4f..9c6e2dfba 100755 --- a/spec/unit/util/zaml_spec.rb +++ b/spec/unit/util/zaml_spec.rb @@ -16,8 +16,24 @@ require 'spec_helper' require 'puppet/util/monkey_patches' describe "Pure ruby yaml implementation" do - def can_round_trip(value) - YAML.load(value.to_yaml).should == value + RSpec::Matchers.define :round_trip_through_yaml do + match do |object| + YAML.load(object.to_yaml) == object + end + end + + RSpec::Matchers.define :be_equivalent_to do |expected_yaml| + match do |object| + object.to_yaml == expected_yaml and YAML.load(expected_yaml) == object + end + + failure_message_for_should do |object| + if object.to_yaml != expected_yaml + "#{object} serialized to #{object.to_yaml}" + else + "#{expected_yaml} deserialized as #{YAML.load(expected_yaml)}" + end + end end { @@ -34,14 +50,67 @@ describe "Pure ruby yaml implementation" do [] => "--- []", :symbol => "--- !ruby/sym symbol", {:a => "A"} => "--- \n !ruby/sym a: A", - {:a => "x\ny"} => "--- \n !ruby/sym a: |-\n x\n y" + {:a => "x\ny"} => "--- \n !ruby/sym a: |-\n x\n y", }.each do |data, serialized| it "should convert the #{data.class} #{data.inspect} to yaml" do - data.to_yaml.should == serialized + data.should be_equivalent_to serialized + end + end + + context Time do + def the_time_in(timezone) + Puppet::Util.withenv("TZ" => timezone) do + Time.local(2012, "dec", 11, 15, 59, 2) + end + end + + def the_time_in_yaml_offset_by(offset) + "--- 2012-12-11 15:59:02.000000 #{offset}" + end + + it "serializes a time in UTC" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("Europe/London").should be_equivalent_to(the_time_in_yaml_offset_by("+00:00")) + end + end + + it "serializes a time behind UTC" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("America/Chicago").should be_equivalent_to(the_time_in_yaml_offset_by("-06:00")) + end end - it "should produce yaml for the #{data.class} #{data.inspect} that can be reconstituted" do - can_round_trip data + it "serializes a time behind UTC that is not a complete hour (Bug #15496)" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("America/Caracas").should be_equivalent_to(the_time_in_yaml_offset_by("-04:30")) + end + end + + it "serializes a time ahead of UTC" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("Europe/Berlin").should be_equivalent_to(the_time_in_yaml_offset_by("+01:00")) + end + end + + it "serializes a time ahead of UTC that is not a complete hour" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("Asia/Kathmandu").should be_equivalent_to(the_time_in_yaml_offset_by("+05:45")) + end + end + + it "serializes a time more than 12 hours ahead of UTC" do + pending("not supported on Windows", :if => Puppet.features.microsoft_windows?) do + the_time_in("Pacific/Kiritimati").should be_equivalent_to(the_time_in_yaml_offset_by("+14:00")) + end + end + + it "should roundtrip Time.now" do + tm = Time.now + # yaml only emits 6 digits of precision, but on some systems with ruby 1.9 + # the original time object may contain nanoseconds, which will cause + # the equality check to fail. So truncate the time object to only microsecs + tm = Time.at(tm.to_i, tm.usec) + tm.should round_trip_through_yaml end end @@ -63,7 +132,7 @@ describe "Pure ruby yaml implementation" do { "b:" => { "a" => [] } } ].each do |value| it "properly escapes #{value.inspect}, which contains YAML characters" do - can_round_trip value + value.should round_trip_through_yaml end end @@ -88,11 +157,7 @@ describe "Pure ruby yaml implementation" do x = [1, 2] y = [3, 4] z = [x, y, x, y] - z.to_yaml.should == "--- \n - &id001\n - 1\n - 2\n - &id002\n - 3\n - 4\n - *id001\n - *id002" - z2 = YAML.load(z.to_yaml) - z2.should == z - z2[0].should equal(z2[2]) - z2[1].should equal(z2[3]) + z.should be_equivalent_to("--- \n - &id001\n - 1\n - 2\n - &id002\n - 3\n - 4\n - *id001\n - *id002") end it "should emit proper labels and backreferences for recursive objects" do @@ -106,141 +171,134 @@ describe "Pure ruby yaml implementation" do x2[1].should == 2 x2[2].should equal(x2) end -end - -# Note, many of these tests will pass on Ruby 1.8 but fail on 1.9 if the patch -# fix is not applied to Puppet or there's a regression. These version -# dependant failures are intentional since the string encoding behavior changed -# significantly in 1.9. -describe "UTF-8 encoded String#to_yaml (Bug #11246)" do - # JJM All of these snowmen are different representations of the same - # UTF-8 encoded string. - let(:snowman) { 'Snowman: [☃]' } - let(:snowman_escaped) { "Snowman: [\xE2\x98\x83]" } - describe "UTF-8 String Literal" do - subject { snowman } + # Note, many of these tests will pass on Ruby 1.8 but fail on 1.9 if the patch + # fix is not applied to Puppet or there's a regression. These version + # dependant failures are intentional since the string encoding behavior changed + # significantly in 1.9. + context "UTF-8 encoded String#to_yaml (Bug #11246)" do + # JJM All of these snowmen are different representations of the same + # UTF-8 encoded string. + let(:snowman) { 'Snowman: [☃]' } + let(:snowman_escaped) { "Snowman: [\xE2\x98\x83]" } - it "should serialize to YAML" do - subject.to_yaml - end it "should serialize and deserialize to the same thing" do - YAML.load(subject.to_yaml).should == subject + snowman.should round_trip_through_yaml end + it "should serialize and deserialize to a String compatible with a UTF-8 encoded Regexp" do - YAML.load(subject.to_yaml).should =~ /☃/u + YAML.load(snowman.to_yaml).should =~ /☃/u end end -end -describe "binary data" do - subject { "M\xC0\xDF\xE5tt\xF6" } + context "binary data" do + subject { "M\xC0\xDF\xE5tt\xF6" } - if String.method_defined?(:encoding) - def binary(str) - str.force_encoding('binary') + if String.method_defined?(:encoding) + def binary(str) + str.force_encoding('binary') + end + else + def binary(str) + str + end end - else - def binary(str) - str - end - end - it "should not explode encoding binary data" do - expect { subject.to_yaml }.not_to raise_error - end + it "should not explode encoding binary data" do + expect { subject.to_yaml }.not_to raise_error + end - it "should mark the binary data as binary" do - subject.to_yaml.should =~ /!binary/ - end + it "should mark the binary data as binary" do + subject.to_yaml.should =~ /!binary/ + end - it "should round-trip the data" do - yaml = subject.to_yaml - read = YAML.load(yaml) - binary(read).should == binary(subject) - end + it "should round-trip the data" do + yaml = subject.to_yaml + read = YAML.load(yaml) + binary(read).should == binary(subject) + end - [ - "\xC0\xAE", # over-long UTF-8 '.' character - "\xC0\x80", # over-long NULL byte - "\xC0\xFF", - "\xC1\xAE", - "\xC1\x80", - "\xC1\xFF", - "\x80", # first continuation byte - "\xbf", # last continuation byte - # all possible continuation bytes in one shot - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" + - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" + - "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" + - "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", - # lonely start characters - first, all possible two byte sequences - "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 \xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF " + - "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 \xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ", - # and so for three byte sequences, four, five, and six, as follow. - "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 \xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ", - "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ", - "\xF8 \xF9 \xFA \xFB ", - "\xFC \xFD ", - # sequences with the last byte missing - "\xC0", "\xE0", "\xF0\x80\x80", "\xF8\x80\x80\x80", "\xFC\x80\x80\x80\x80", - "\xDF", "\xEF\xBF", "\xF7\xBF\xBF", "\xFB\xBF\xBF\xBF", "\xFD\xBF\xBF\xBF\xBF", - # impossible bytes - "\xFE", "\xFF", "\xFE\xFE\xFF\xFF", - # over-long '/' character - "\xC0\xAF", - "\xE0\x80\xAF", - "\xF0\x80\x80\xAF", - "\xF8\x80\x80\x80\xAF", - "\xFC\x80\x80\x80\x80\xAF", - # maximum overlong sequences - "\xc1\xbf", - "\xe0\x9f\xbf", - "\xf0\x8f\xbf\xbf", - "\xf8\x87\xbf\xbf\xbf", - "\xfc\x83\xbf\xbf\xbf\xbf", - # overlong NUL - "\xc0\x80", - "\xe0\x80\x80", - "\xf0\x80\x80\x80", - "\xf8\x80\x80\x80\x80", - "\xfc\x80\x80\x80\x80\x80", - ].each do |input| - # It might seem like we should more correctly reject these sequences in - # the encoder, and I would personally agree, but the sad reality is that - # we do not distinguish binary and textual data in our language, and so we - # wind up with the same thing - a string - containing both. - # - # That leads to the position where we must treat these invalid sequences, - # which are both legitimate binary content, and illegitimate potential - # attacks on the system, as something that passes through correctly in - # a string. --daniel 2012-07-14 - it "binary encode highly dubious non-compliant UTF-8 input #{input.inspect}" do - encoded = ZAML.dump(binary(input)) - encoded.should =~ /!binary/ - YAML.load(encoded).should == input + [ + "\xC0\xAE", # over-long UTF-8 '.' character + "\xC0\x80", # over-long NULL byte + "\xC0\xFF", + "\xC1\xAE", + "\xC1\x80", + "\xC1\xFF", + "\x80", # first continuation byte + "\xbf", # last continuation byte + # all possible continuation bytes in one shot + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" + + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" + + "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" + + "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF", + # lonely start characters - first, all possible two byte sequences + "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 \xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF " + + "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 \xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ", + # and so for three byte sequences, four, five, and six, as follow. + "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 \xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ", + "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ", + "\xF8 \xF9 \xFA \xFB ", + "\xFC \xFD ", + # sequences with the last byte missing + "\xC0", "\xE0", "\xF0\x80\x80", "\xF8\x80\x80\x80", "\xFC\x80\x80\x80\x80", + "\xDF", "\xEF\xBF", "\xF7\xBF\xBF", "\xFB\xBF\xBF\xBF", "\xFD\xBF\xBF\xBF\xBF", + # impossible bytes + "\xFE", "\xFF", "\xFE\xFE\xFF\xFF", + # over-long '/' character + "\xC0\xAF", + "\xE0\x80\xAF", + "\xF0\x80\x80\xAF", + "\xF8\x80\x80\x80\xAF", + "\xFC\x80\x80\x80\x80\xAF", + # maximum overlong sequences + "\xc1\xbf", + "\xe0\x9f\xbf", + "\xf0\x8f\xbf\xbf", + "\xf8\x87\xbf\xbf\xbf", + "\xfc\x83\xbf\xbf\xbf\xbf", + # overlong NUL + "\xc0\x80", + "\xe0\x80\x80", + "\xf0\x80\x80\x80", + "\xf8\x80\x80\x80\x80", + "\xfc\x80\x80\x80\x80\x80", + ].each do |input| + # It might seem like we should more correctly reject these sequences in + # the encoder, and I would personally agree, but the sad reality is that + # we do not distinguish binary and textual data in our language, and so we + # wind up with the same thing - a string - containing both. + # + # That leads to the position where we must treat these invalid sequences, + # which are both legitimate binary content, and illegitimate potential + # attacks on the system, as something that passes through correctly in + # a string. --daniel 2012-07-14 + it "binary encode highly dubious non-compliant UTF-8 input #{input.inspect}" do + encoded = ZAML.dump(binary(input)) + encoded.should =~ /!binary/ + YAML.load(encoded).should == input + end end end -end -describe "multi-line values" do - [ - "none", - "one\n", - "two\n\n", - ["one\n", "two"], - ["two\n\n", "three"], - { "\nkey" => "value" }, - { "key\n" => "value" }, - { "\nkey\n" => "value" }, - { "key\nkey" => "value" }, - { "\nkey\nkey" => "value" }, - { "key\nkey\n" => "value" }, - { "\nkey\nkey\n" => "value" }, - ].each do |input| - it "handles #{input.inspect} without corruption" do - zaml = ZAML.dump(input) - YAML.load(zaml).should == input + context "multi-line values" do + [ + "none", + "one\n", + "two\n\n", + ["one\n", "two"], + ["two\n\n", "three"], + { "\nkey" => "value" }, + { "key\n" => "value" }, + { "\nkey\n" => "value" }, + { "key\nkey" => "value" }, + { "\nkey\nkey" => "value" }, + { "key\nkey\n" => "value" }, + { "\nkey\nkey\n" => "value" }, + ].each do |input| + it "handles #{input.inspect} without corruption" do + input.should round_trip_through_yaml + end end end end diff --git a/spec/unit/version_spec.rb b/spec/unit/version_spec.rb new file mode 100644 index 000000000..d2e8b5138 --- /dev/null +++ b/spec/unit/version_spec.rb @@ -0,0 +1,42 @@ +require "spec_helper" +require "puppet/version" +require 'pathname' + +describe "Puppet.version Public API" do + before :each do + Puppet.instance_eval do + if @puppet_version + @puppet_version = nil + end + end + end + + context "without a VERSION file" do + before :each do + Puppet.stubs(:read_version_file).returns(nil) + end + + it "is Puppet::PUPPETVERSION" do + Puppet.version.should == Puppet::PUPPETVERSION + end + it "respects the version= setter" do + Puppet.version = '1.2.3' + Puppet.version.should == '1.2.3' + end + end + + context "with a VERSION file" do + it "is the content of the file" do + Puppet.expects(:read_version_file).with() do |path| + pathname = Pathname.new(path) + pathname.basename.to_s == "VERSION" + end.returns('3.0.1-260-g9ca4e54') + + Puppet.version.should == '3.0.1-260-g9ca4e54' + end + it "respects the version= setter" do + Puppet.version = '1.2.3' + Puppet.version.should == '1.2.3' + end + end +end |
