diff options
Diffstat (limited to 'spec')
146 files changed, 3003 insertions, 1537 deletions
diff --git a/spec/integration/application/doc_spec.rb b/spec/integration/application/doc_spec.rb index 9412976f0..2cf5fd1e9 100755 --- a/spec/integration/application/doc_spec.rb +++ b/spec/integration/application/doc_spec.rb @@ -5,7 +5,7 @@ require 'puppet_spec/files' describe Puppet::Application::Doc do include PuppetSpec::Files - it "should not generate an error when module dir overlaps parent of site.pp (#4798)", :'fails_on_ruby_1.9.2' => true do + it "should not generate an error when module dir overlaps parent of site.pp (#4798)", :'fails_on_ruby_1.9.2' => true, :unless => Puppet.features.microsoft_windows? do begin # Note: the directory structure below is more complex than it # needs to be, but it's representative of the directory structure diff --git a/spec/integration/defaults_spec.rb b/spec/integration/defaults_spec.rb index 9bec769ab..84297e8f9 100755 --- a/spec/integration/defaults_spec.rb +++ b/spec/integration/defaults_spec.rb @@ -275,6 +275,16 @@ describe "Puppet defaults" do describe "reporturl" do subject { Puppet.settings[:reporturl] } - it { should == "http://localhost:3000/reports" } + it { should == "http://localhost:3000/reports/upload" } + end + + describe "when configuring color" do + it "should default to ansi", :unless => Puppet.features.microsoft_windows? do + Puppet.settings[:color].should == 'ansi' + end + + it "should default to false", :if => Puppet.features.microsoft_windows? do + Puppet.settings[:color].should == 'false' + end end end diff --git a/spec/integration/file_serving/content_spec.rb b/spec/integration/file_serving/content_spec.rb index a95ddc520..e82b726fe 100755 --- a/spec/integration/file_serving/content_spec.rb +++ b/spec/integration/file_serving/content_spec.rb @@ -15,6 +15,4 @@ describe Puppet::FileServing::Content, " when finding files" do @test_class = Puppet::FileServing::Content @indirection = Puppet::FileServing::Content.indirection end - - after { Puppet::Util::Cacher.expire } end diff --git a/spec/integration/file_serving/metadata_spec.rb b/spec/integration/file_serving/metadata_spec.rb index ba7d3311f..8b4d53d6b 100755 --- a/spec/integration/file_serving/metadata_spec.rb +++ b/spec/integration/file_serving/metadata_spec.rb @@ -16,6 +16,4 @@ describe Puppet::FileServing::Metadata, " when finding files" do @test_class = Puppet::FileServing::Metadata @indirection = Puppet::FileServing::Metadata.indirection end - - after { Puppet::Util::Cacher.expire } end diff --git a/spec/integration/file_serving/terminus_helper_spec.rb b/spec/integration/file_serving/terminus_helper_spec.rb index 7500b1fc0..99fee9ce5 100755 --- a/spec/integration/file_serving/terminus_helper_spec.rb +++ b/spec/integration/file_serving/terminus_helper_spec.rb @@ -10,7 +10,7 @@ class TerminusHelperIntegrationTester end end -describe Puppet::FileServing::TerminusHelper do +describe Puppet::FileServing::TerminusHelper, :fails_on_windows => true do it "should be able to recurse on a single file" do @path = Tempfile.new("fileset_integration") request = Puppet::Indirector::Request.new(:metadata, :find, @path.path, :recurse => true) diff --git a/spec/integration/indirector/direct_file_server_spec.rb b/spec/integration/indirector/direct_file_server_spec.rb index e53b48d69..68ed00740 100755 --- a/spec/integration/indirector/direct_file_server_spec.rb +++ b/spec/integration/indirector/direct_file_server_spec.rb @@ -7,12 +7,14 @@ require 'spec_helper' require 'puppet/indirector/file_content/file' -describe Puppet::Indirector::DirectFileServer, " when interacting with the filesystem and the model" do +describe Puppet::Indirector::DirectFileServer, " when interacting with the filesystem and the model", :fails_on_windows => true do + include PuppetSpec::Files + before do # We just test a subclass, since it's close enough. @terminus = Puppet::Indirector::FileContent::File.new - @filepath = "/path/to/my/file" + @filepath = make_absolute("/path/to/my/file") end it "should return an instance of the model" do @@ -32,7 +34,7 @@ describe Puppet::Indirector::DirectFileServer, " when interacting with the files end end -describe Puppet::Indirector::DirectFileServer, " when interacting with FileServing::Fileset and the model" do +describe Puppet::Indirector::DirectFileServer, " when interacting with FileServing::Fileset and the model", :fails_on_windows => true do before do @terminus = Puppet::Indirector::FileContent::File.new diff --git a/spec/integration/indirector/file_content/file_server_spec.rb b/spec/integration/indirector/file_content/file_server_spec.rb index 88d2345d8..86b75006a 100755 --- a/spec/integration/indirector/file_content/file_server_spec.rb +++ b/spec/integration/indirector/file_content/file_server_spec.rb @@ -10,13 +10,14 @@ require 'shared_behaviours/file_server_terminus' require 'puppet_spec/files' -describe Puppet::Indirector::FileContent::FileServer, " when finding files" do +describe Puppet::Indirector::FileContent::FileServer, " when finding files", :fails_on_windows => true do it_should_behave_like "Puppet::Indirector::FileServerTerminus" include PuppetSpec::Files before do @terminus = Puppet::Indirector::FileContent::FileServer.new @test_class = Puppet::FileServing::Content + Puppet::FileServing::Configuration.instance_variable_set(:@configuration, nil) end it "should find plugin file content in the environment specified in the request" do @@ -62,7 +63,6 @@ describe Puppet::Indirector::FileContent::FileServer, " when finding files" do end it "should find file content in files when node name expansions are used" do - Puppet::Util::Cacher.expire FileTest.stubs(:exists?).returns true FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true) diff --git a/spec/integration/indirector/file_metadata/file_server_spec.rb b/spec/integration/indirector/file_metadata/file_server_spec.rb index 9e84134a6..5259837fc 100755 --- a/spec/integration/indirector/file_metadata/file_server_spec.rb +++ b/spec/integration/indirector/file_metadata/file_server_spec.rb @@ -8,7 +8,7 @@ require 'spec_helper' require 'puppet/indirector/file_metadata/file_server' require 'shared_behaviours/file_server_terminus' -describe Puppet::Indirector::FileMetadata::FileServer, " when finding files" do +describe Puppet::Indirector::FileMetadata::FileServer, " when finding files", :fails_on_windows => true do it_should_behave_like "Puppet::Indirector::FileServerTerminus" before do diff --git a/spec/integration/network/rest_authconfig_spec.rb b/spec/integration/network/rest_authconfig_spec.rb new file mode 100644 index 000000000..d2f539cd4 --- /dev/null +++ b/spec/integration/network/rest_authconfig_spec.rb @@ -0,0 +1,145 @@ +require 'spec_helper' + +require 'puppet/network/rest_authconfig' + +RSpec::Matchers.define :allow do |params| + + match do |auth| + begin + auth.check_authorization(params[0], params[1], params[2], params[3]) + true + rescue Puppet::Network::AuthorizationError + false + end + end + + failure_message_for_should do |instance| + "expected #{params[3][:node]}/#{params[3][:ip]} to be allowed" + end + + failure_message_for_should_not do |instance| + "expected #{params[3][:node]}/#{params[3][:ip]} to be forbidden" + end +end + +describe Puppet::Network::RestAuthConfig do + include PuppetSpec::Files + + before(:each) do + Puppet[:rest_authconfig] = tmpfile('auth.conf') + end + + def add_rule(rule) + File.open(Puppet[:rest_authconfig],"w+") do |f| + f.print "path /test\n#{rule}\n" + end + @auth = Puppet::Network::RestAuthConfig.new(Puppet[:rest_authconfig], true) + end + + def add_regex_rule(regex, rule) + File.open(Puppet[:rest_authconfig],"w+") do |f| + f.print "path ~ #{regex}\n#{rule}\n" + end + @auth = Puppet::Network::RestAuthConfig.new(Puppet[:rest_authconfig], true) + end + + def request(args = {}) + { :ip => '10.1.1.1', :node => 'host.domain.com', :key => 'key', :authenticated => true }.each do |k,v| + args[k] ||= v + end + ['test', :find, args[:key], args] + end + + it "should support IPv4 address" do + add_rule("allow 10.1.1.1") + + @auth.should allow(request) + end + + it "should support CIDR IPv4 address" do + add_rule("allow 10.0.0.0/8") + + @auth.should allow(request) + end + + it "should support wildcard IPv4 address" do + add_rule("allow 10.1.1.*") + + @auth.should allow(request) + end + + it "should support IPv6 address" do + add_rule("allow 2001:DB8::8:800:200C:417A") + + @auth.should allow(request(:ip => '2001:DB8::8:800:200C:417A')) + end + + it "should support hostname" do + add_rule("allow host.domain.com") + + @auth.should allow(request) + end + + it "should support wildcard host" do + add_rule("allow *.domain.com") + + @auth.should allow(request) + end + + it "should support hostname backreferences" do + add_regex_rule('^/test/([^/]+)$', "allow $1.domain.com") + + @auth.should allow(request(:key => 'host')) + end + + it "should support opaque strings" do + add_rule("allow this-is-opaque@or-not") + + @auth.should allow(request(:node => 'this-is-opaque@or-not')) + end + + it "should support opaque strings and backreferences" do + add_regex_rule('^/test/([^/]+)$', "allow $1") + + @auth.should allow(request(:key => 'this-is-opaque@or-not', :node => 'this-is-opaque@or-not')) + end + + it "should support hostname ending with '.'" do + pending('bug #7589') + add_rule("allow host.domain.com.") + + @auth.should allow(request(:node => 'host.domain.com.')) + end + + it "should support hostname ending with '.' and backreferences" do + pending('bug #7589') + add_regex_rule('^/test/([^/]+)$',"allow $1") + + @auth.should allow(request(:node => 'host.domain.com.')) + end + + it "should support trailing whitespace" do + add_rule('allow host.domain.com ') + + @auth.should allow(request) + end + + it "should support inlined comments" do + add_rule('allow host.domain.com # will it work?') + + @auth.should allow(request) + end + + it "should deny non-matching host" do + add_rule("allow inexistant") + + @auth.should_not allow(request) + end + + it "should deny denied hosts" do + add_rule("deny host.domain.com") + + @auth.should_not allow(request) + end + +end
\ No newline at end of file diff --git a/spec/integration/network/server/webrick_spec.rb b/spec/integration/network/server/webrick_spec.rb index 81c35af4f..7365462d3 100755 --- a/spec/integration/network/server/webrick_spec.rb +++ b/spec/integration/network/server/webrick_spec.rb @@ -4,7 +4,9 @@ require 'puppet/network/server' require 'puppet/ssl/certificate_authority' require 'socket' -describe Puppet::Network::Server do +describe Puppet::Network::Server, :unless => Puppet.features.microsoft_windows? do + include PuppetSpec::Files + describe "when using webrick" do before :each do Puppet[:servertype] = 'webrick' @@ -12,11 +14,10 @@ describe Puppet::Network::Server do @params = { :port => 34343, :handlers => [ :node ], :xmlrpc_handlers => [ :status ] } # Get a safe temporary file - @tmpfile = Tempfile.new("webrick_integration_testing") - @dir = @tmpfile.path + "_dir" + dir = tmpdir("webrick_integration_testing") - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir Puppet.settings[:group] = Process.gid Puppet::SSL::Host.ca_location = :local @@ -26,13 +27,9 @@ describe Puppet::Network::Server do end after do - @tmpfile.delete Puppet.settings.clear - system("rm -rf #{@dir}") - Puppet::SSL::Host.ca_location = :none - Puppet::Util::Cacher.expire end describe "before listening" do diff --git a/spec/integration/node/facts_spec.rb b/spec/integration/node/facts_spec.rb index f54d7f9aa..4ec4bc821 100755 --- a/spec/integration/node/facts_spec.rb +++ b/spec/integration/node/facts_spec.rb @@ -7,8 +7,6 @@ require 'spec_helper' describe Puppet::Node::Facts do describe "when using the indirector" do - after { Puppet::Util::Cacher.expire } - it "should expire any cached node instances when it is saved" do Puppet::Node::Facts.indirection.stubs(:terminus_class).returns :yaml diff --git a/spec/integration/parser/functions_spec.rb b/spec/integration/parser/functions_spec.rb index 6791987d7..6a8fbca9c 100755 --- a/spec/integration/parser/functions_spec.rb +++ b/spec/integration/parser/functions_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Puppet::Parser::Functions do before :each do - Puppet::Parser::Functions.rmfunction("template") if Puppet::Parser::Functions.function("template") + Puppet::Parser::Functions.rmfunction("template") if Puppet::Parser::Functions.functions.include?("template") end it "should support multiple threads autoloading the same function" do diff --git a/spec/integration/provider/mount_spec.rb b/spec/integration/provider/mount_spec.rb index 4af0dca4a..b2e9c4497 100755 --- a/spec/integration/provider/mount_spec.rb +++ b/spec/integration/provider/mount_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' require 'puppet/file_bucket/dipper' -describe "mount provider (integration)" do +describe "mount provider (integration)", :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files def create_fake_fstab(initially_contains_entry) diff --git a/spec/integration/provider/package_spec.rb b/spec/integration/provider/package_spec.rb index 5fecdf13c..701752371 100755 --- a/spec/integration/provider/package_spec.rb +++ b/spec/integration/provider/package_spec.rb @@ -12,7 +12,7 @@ describe "Package Provider", :'fails_on_ruby_1.9.2' => true do lambda { pkg.provider.install }.should raise_error end - it "should be able to get a list of existing packages" do + it "should be able to get a list of existing packages", :fails_on_windows => true do provider.instances.each do |package| package.should be_instance_of(provider) package.properties[:provider].should == provider.name diff --git a/spec/integration/provider/ssh_authorized_key_spec.rb b/spec/integration/provider/ssh_authorized_key_spec.rb index 902f9ad22..252f7bf78 100644..100755 --- a/spec/integration/provider/ssh_authorized_key_spec.rb +++ b/spec/integration/provider/ssh_authorized_key_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'puppet/file_bucket/dipper' -describe "ssh_authorized_key provider (integration)" do +describe "ssh_authorized_key provider (integration)", :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files before :each do diff --git a/spec/integration/resource/catalog_spec.rb b/spec/integration/resource/catalog_spec.rb index 41a475d98..ae15ee453 100755 --- a/spec/integration/resource/catalog_spec.rb +++ b/spec/integration/resource/catalog_spec.rb @@ -13,7 +13,6 @@ describe Puppet::Resource::Catalog do end describe "when using the indirector" do - after { Puppet::Util::Cacher.expire } before do # This is so the tests work w/out networking. Facter.stubs(:to_hash).returns({"hostname" => "foo.domain.com"}) diff --git a/spec/integration/ssl/certificate_authority_spec.rb b/spec/integration/ssl/certificate_authority_spec.rb index c5e145459..dc8af6a7b 100755 --- a/spec/integration/ssl/certificate_authority_spec.rb +++ b/spec/integration/ssl/certificate_authority_spec.rb @@ -6,17 +6,16 @@ require 'spec_helper' require 'puppet/ssl/certificate_authority' -require 'tempfile' -describe Puppet::SSL::CertificateAuthority do +describe Puppet::SSL::CertificateAuthority, :unless => Puppet.features.microsoft_windows? do + include PuppetSpec::Files + before do # Get a safe temporary file - file = Tempfile.new("ca_integration_testing") - @dir = file.path - file.delete + dir = tmpdir("ca_integration_testing") - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir Puppet.settings[:group] = Process.gid Puppet::SSL::Host.ca_location = :local @@ -26,11 +25,8 @@ describe Puppet::SSL::CertificateAuthority do after { Puppet::SSL::Host.ca_location = :none - system("rm -rf #{@dir}") Puppet.settings.clear - Puppet::Util::Cacher.expire - Puppet::SSL::CertificateAuthority.instance_variable_set("@instance", nil) } diff --git a/spec/integration/ssl/certificate_request_spec.rb b/spec/integration/ssl/certificate_request_spec.rb index 688466c37..6c1c8b964 100755 --- a/spec/integration/ssl/certificate_request_spec.rb +++ b/spec/integration/ssl/certificate_request_spec.rb @@ -6,21 +6,19 @@ require 'spec_helper' require 'puppet/ssl/certificate_request' -require 'tempfile' -describe Puppet::SSL::CertificateRequest do +# REMIND: Fails on windows because there is no user provider yet +describe Puppet::SSL::CertificateRequest, :fails_on_windows => true do + include PuppetSpec::Files + before do # Get a safe temporary file - file = Tempfile.new("csr_integration_testing") - @dir = file.path - file.delete - - Dir.mkdir(@dir) + dir = tmpdir("csr_integration_testing") Puppet.settings.clear - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir Puppet.settings[:group] = Process.gid Puppet::SSL::Host.ca_location = :none @@ -28,14 +26,13 @@ describe Puppet::SSL::CertificateRequest do @csr = Puppet::SSL::CertificateRequest.new("luke.madstop.com") @key = OpenSSL::PKey::RSA.new(512) + + # This is necessary so the terminus instances don't lie around. + Puppet::SSL::CertificateRequest.indirection.termini.clear end after do - system("rm -rf #{@dir}") Puppet.settings.clear - - # This is necessary so the terminus instances don't lie around. - Puppet::Util::Cacher.expire end it "should be able to generate CSRs" do diff --git a/spec/integration/ssl/certificate_revocation_list_spec.rb b/spec/integration/ssl/certificate_revocation_list_spec.rb index 051a81569..d140fd950 100755 --- a/spec/integration/ssl/certificate_revocation_list_spec.rb +++ b/spec/integration/ssl/certificate_revocation_list_spec.rb @@ -6,17 +6,17 @@ require 'spec_helper' require 'puppet/ssl/certificate_revocation_list' -require 'tempfile' -describe Puppet::SSL::CertificateRevocationList do +# REMIND: Fails on windows because there is no user provider yet +describe Puppet::SSL::CertificateRevocationList, :fails_on_windows => true do + include PuppetSpec::Files + before do # Get a safe temporary file - file = Tempfile.new("ca_integration_testing") - @dir = file.path - file.delete + dir = tmpdir("ca_integration_testing") - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir Puppet.settings[:group] = Process.gid Puppet::SSL::Host.ca_location = :local @@ -25,11 +25,10 @@ describe Puppet::SSL::CertificateRevocationList do after { Puppet::SSL::Host.ca_location = :none - system("rm -rf #{@dir}") Puppet.settings.clear # This is necessary so the terminus instances don't lie around. - Puppet::Util::Cacher.expire + Puppet::SSL::Host.indirection.termini.clear } it "should be able to read in written out CRLs with no revoked certificates" do diff --git a/spec/integration/ssl/host_spec.rb b/spec/integration/ssl/host_spec.rb index e9c37c151..94e245554 100755 --- a/spec/integration/ssl/host_spec.rb +++ b/spec/integration/ssl/host_spec.rb @@ -6,17 +6,17 @@ require 'spec_helper' require 'puppet/ssl/host' -require 'tempfile' -describe Puppet::SSL::Host do +# REMIND: Fails on windows because there is no user provider yet +describe Puppet::SSL::Host, :fails_on_windows => true do + include PuppetSpec::Files + before do # Get a safe temporary file - file = Tempfile.new("host_integration_testing") - @dir = file.path - file.delete + dir = tmpdir("host_integration_testing") - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir Puppet.settings[:group] = Process.gid Puppet::SSL::Host.ca_location = :local @@ -28,9 +28,7 @@ describe Puppet::SSL::Host do after { Puppet::SSL::Host.ca_location = :none - system("rm -rf #{@dir}") Puppet.settings.clear - Puppet::Util::Cacher.expire } it "should be considered a CA host if its name is equal to 'ca'" do @@ -81,7 +79,7 @@ describe Puppet::SSL::Host do end end - it "should pass the verification of its own SSL store" do + it "should pass the verification of its own SSL store", :unless => Puppet.features.microsoft_windows? do @host.generate @ca = Puppet::SSL::CertificateAuthority.new @ca.sign(@host.name) diff --git a/spec/integration/transaction/report_spec.rb b/spec/integration/transaction/report_spec.rb index 183d93f76..315c0c099 100755 --- a/spec/integration/transaction/report_spec.rb +++ b/spec/integration/transaction/report_spec.rb @@ -8,7 +8,6 @@ require 'spec_helper' describe Puppet::Transaction::Report do describe "when using the indirector" do after do - Puppet::Util::Cacher.expire Puppet.settings.stubs(:use) end diff --git a/spec/integration/transaction_spec.rb b/spec/integration/transaction_spec.rb index 00e9dbb8e..b4214214e 100755 --- a/spec/integration/transaction_spec.rb +++ b/spec/integration/transaction_spec.rb @@ -1,9 +1,7 @@ #!/usr/bin/env rspec require 'spec_helper' -require 'puppet_spec/files' require 'puppet/transaction' -require 'puppet_spec/files' describe Puppet::Transaction do include PuppetSpec::Files @@ -20,10 +18,10 @@ describe Puppet::Transaction do it "should not apply generated resources if the parent resource fails" do catalog = Puppet::Resource::Catalog.new - resource = Puppet::Type.type(:file).new :path => "/foo/bar", :backup => false + resource = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar"), :backup => false catalog.add_resource resource - child_resource = Puppet::Type.type(:file).new :path => "/foo/bar/baz", :backup => false + child_resource = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar/baz"), :backup => false resource.expects(:eval_generate).returns([child_resource]) @@ -39,7 +37,7 @@ describe Puppet::Transaction do it "should not apply virtual resources" do catalog = Puppet::Resource::Catalog.new - resource = Puppet::Type.type(:file).new :path => "/foo/bar", :backup => false + resource = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar"), :backup => false resource.virtual = true catalog.add_resource resource @@ -63,7 +61,7 @@ describe Puppet::Transaction do it "should not apply virtual exported resources" do catalog = Puppet::Resource::Catalog.new - resource = Puppet::Type.type(:file).new :path => "/foo/bar", :backup => false + resource = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar"), :backup => false resource.exported = true resource.virtual = true catalog.add_resource resource @@ -91,7 +89,7 @@ describe Puppet::Transaction do it "should not apply host resources on device" do catalog = Puppet::Resource::Catalog.new - resource = Puppet::Type.type(:file).new :path => "/foo/bar", :backup => false + resource = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar"), :backup => false catalog.add_resource resource transaction = Puppet::Transaction.new(catalog) @@ -133,7 +131,7 @@ describe Puppet::Transaction do # Verify that one component requiring another causes the contained # resources in the requiring component to get refreshed. - it "should propagate events from a contained resource through its container to its dependent container's contained resources" do + it "should propagate events from a contained resource through its container to its dependent container's contained resources", :fails_on_windows => true do transaction = nil file = Puppet::Type.type(:file).new :path => tmpfile("event_propagation"), :ensure => :present execfile = File.join(tmpdir("exec_event"), "exectestingness2") @@ -157,7 +155,7 @@ describe Puppet::Transaction do end # Make sure that multiple subscriptions get triggered. - it "should propagate events to all dependent resources" do + it "should propagate events to all dependent resources", :fails_on_windows => true do path = tmpfile("path") file1 = tmpfile("file1") file2 = tmpfile("file2") @@ -187,7 +185,7 @@ describe Puppet::Transaction do FileTest.should be_exist(file2) end - it "should not let one failed refresh result in other refreshes failing" do + it "should not let one failed refresh result in other refreshes failing", :fails_on_windows => true do path = tmpfile("path") newfile = tmpfile("file") file = Puppet::Type.type(:file).new( @@ -220,7 +218,7 @@ describe Puppet::Transaction do FileTest.should be_exists(newfile) end - it "should still trigger skipped resources", :'fails_on_ruby_1.9.2' => true do + it "should still trigger skipped resources", :'fails_on_ruby_1.9.2' => true, :fails_on_windows => true do catalog = mk_catalog catalog.add_resource(*Puppet::Type.type(:schedule).mkdefaultschedules) @@ -272,7 +270,7 @@ describe Puppet::Transaction do FileTest.should be_exists(fname) end - it "should not attempt to evaluate resources with failed dependencies" do + it "should not attempt to evaluate resources with failed dependencies", :fails_on_windows => true do exec = Puppet::Type.type(:exec).new( :command => "/bin/mkdir /this/path/cannot/possibly/exist", @@ -300,7 +298,7 @@ describe Puppet::Transaction do FileTest.should_not be_exists(file2[:path]) end - it "should not trigger subscribing resources on failure" do + it "should not trigger subscribing resources on failure", :fails_on_windows => true do file1 = tmpfile("file1") file2 = tmpfile("file2") diff --git a/spec/integration/type/file_spec.rb b/spec/integration/type/file_spec.rb index 4bed8c6c1..9814c4539 100755 --- a/spec/integration/type/file_spec.rb +++ b/spec/integration/type/file_spec.rb @@ -12,7 +12,7 @@ describe Puppet::Type.type(:file) do end it "should not attempt to manage files that do not exist if no means of creating the file is specified" do - file = Puppet::Type.type(:file).new :path => "/my/file", :mode => "755" + file = Puppet::Type.type(:file).new :path => make_absolute("/my/file"), :mode => "755" catalog = Puppet::Resource::Catalog.new catalog.add_resource file @@ -23,7 +23,7 @@ describe Puppet::Type.type(:file) do end describe "when writing files" do - it "should backup files to a filebucket when one is configured" do + it "should backup files to a filebucket when one is configured", :fails_on_windows => true do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo" catalog = Puppet::Resource::Catalog.new @@ -73,7 +73,7 @@ describe Puppet::Type.type(:file) do File.read(file[:path]).should == "bar\n" end - it "should not backup symlinks" do + it "should not backup symlinks", :unless => Puppet.features.microsoft_windows? do link = tmpfile("link") dest1 = tmpfile("dest1") dest2 = tmpfile("dest2") @@ -110,7 +110,7 @@ describe Puppet::Type.type(:file) do File.read(File.join(backup, "foo")).should == "yay" end - it "should backup directories to filebuckets by backing up each file separately" do + it "should backup directories to filebuckets by backing up each file separately", :fails_on_windows => true do bucket = Puppet::Type.type(:filebucket).new :path => tmpfile("filebucket"), :name => "mybucket" file = Puppet::Type.type(:file).new :path => tmpfile("bucket_backs"), :backup => "mybucket", :content => "foo", :force => true catalog = Puppet::Resource::Catalog.new @@ -172,7 +172,7 @@ describe Puppet::Type.type(:file) do end end - it "should be able to recurse over a nonexistent file" do + it "should be able to recurse over a nonexistent file", :fails_on_windows => true do @path = tmpfile("file_integration_tests") @file = Puppet::Type::File.new( @@ -214,7 +214,7 @@ describe Puppet::Type.type(:file) do end end - it "should be able to recursively make links to other files" do + it "should be able to recursively make links to other files", :unless => Puppet.features.microsoft_windows? do source = tmpfile("file_link_integration_source") build_path(source) @@ -241,7 +241,7 @@ describe Puppet::Type.type(:file) do end end - it "should be able to recursively copy files" do + it "should be able to recursively copy files", :fails_on_windows => true do source = tmpfile("file_source_integration_source") build_path(source) @@ -292,24 +292,25 @@ describe Puppet::Type.type(:file) do it "should recursively manage files even if there is an explicit file whose name is a prefix of the managed file" do dir = tmpfile("recursion_vs_explicit_2") - managed = File.join(dir, "file") - generated = File.join(dir, "file_with_a_name_starting_with_the_word_file") + managed = File.join(dir, "file") + generated = File.join(dir, "file_with_a_name_starting_with_the_word_file") + managed_mode = Puppet.features.microsoft_windows? ? 0444 : 0700 FileUtils.mkdir_p(dir) File.open(managed, "w") { |f| f.puts "" } File.open(generated, "w") { |f| f.puts "" } @catalog = Puppet::Resource::Catalog.new - @catalog.add_resource Puppet::Type::File.new(:name => dir, :recurse => true, :backup => false, :mode => "755") + @catalog.add_resource Puppet::Type::File.new(:name => dir, :recurse => true, :backup => false, :mode => managed_mode) @catalog.add_resource Puppet::Type::File.new(:name => managed, :recurse => true, :backup => false, :mode => "644") @catalog.apply - (File.stat(generated).mode & 007777).should == 0755 + (File.stat(generated).mode & 007777).should == managed_mode end end - describe "when generating resources" do + describe "when generating resources", :fails_on_windows => true do before do @source = tmpfile("generating_in_catalog_source") @@ -381,8 +382,9 @@ describe Puppet::Type.type(:file) do catalog.apply + expected_mode = Puppet.features.microsoft_windows? ? 0644 : 0755 File.read(dest).should == "foo" - (File.stat(dest).mode & 007777).should == 0755 + (File.stat(dest).mode & 007777).should == expected_mode end it "should be able to copy individual files even if recurse has been specified" do @@ -442,7 +444,7 @@ describe Puppet::Type.type(:file) do file = Puppet::Type.type(:file).new( - :name => dest, + :name => make_absolute(dest), :ensure => :absent, :source => source, :backup => false @@ -470,7 +472,6 @@ describe Puppet::Type.type(:file) do # this file should get removed File.open(@purgee, "w") { |f| f.puts "footest" } - @lfobj = Puppet::Type.newfile( :title => "localfile", :path => @localfile, @@ -479,7 +480,6 @@ describe Puppet::Type.type(:file) do :backup => false ) - @destobj = Puppet::Type.newfile( :title => "destdir", :path => @destdir, diff --git a/spec/integration/type/tidy_spec.rb b/spec/integration/type/tidy_spec.rb index 675aaf4cd..d1bb62d6e 100755 --- a/spec/integration/type/tidy_spec.rb +++ b/spec/integration/type/tidy_spec.rb @@ -12,7 +12,7 @@ describe Puppet::Type.type(:tidy) do end # Testing #355. - it "should be able to remove dead links" do + it "should be able to remove dead links", :unless => Puppet.features.microsoft_windows? do dir = tmpfile("tidy_link_testing") link = File.join(dir, "link") target = tmpfile("no_such_file_tidy_link_testing") diff --git a/spec/integration/util/settings_spec.rb b/spec/integration/util/settings_spec.rb index b05c63107..46d783c4e 100755 --- a/spec/integration/util/settings_spec.rb +++ b/spec/integration/util/settings_spec.rb @@ -18,12 +18,12 @@ describe Puppet::Util::Settings do File.should be_directory(settings[:maindir]) end - it "should make its directories with the corret modes" do + it "should make its directories with the correct modes" do settings = Puppet::Util::Settings.new settings.setdefaults :main, minimal_default_settings.update( :maindir => {:default => tmpfile("main"), :desc => "a", :mode => 0750} ) settings.use(:main) - (File.stat(settings[:maindir]).mode & 007777).should == 0750 + (File.stat(settings[:maindir]).mode & 007777).should == (Puppet.features.microsoft_windows? ? 0755 : 0750) end end diff --git a/spec/lib/puppet/face/1.0.0/huzzah.rb b/spec/lib/puppet/face/1.0.0/huzzah.rb new file mode 100755 index 000000000..8a1311704 --- /dev/null +++ b/spec/lib/puppet/face/1.0.0/huzzah.rb @@ -0,0 +1,8 @@ +require 'puppet/face' +Puppet::Face.define(:huzzah, '1.0.0') do + copyright "Puppet Labs", 2011 + license "Apache 2 license; see COPYING" + summary "life is a thing for celebration" + script :obsolete_in_core do |_| "you are in obsolete core now!" end + script :call_newer do |_| method_on_newer end +end diff --git a/spec/lib/puppet/face/huzzah.rb b/spec/lib/puppet/face/huzzah.rb index ab465d9e0..f3d18a797 100755 --- a/spec/lib/puppet/face/huzzah.rb +++ b/spec/lib/puppet/face/huzzah.rb @@ -4,4 +4,5 @@ Puppet::Face.define(:huzzah, '2.0.1') do license "Apache 2 license; see COPYING" summary "life is a thing for celebration" script :bar do |options| "is where beer comes from" end + script :call_older do |_| method_on_older end end diff --git a/spec/lib/puppet/face/huzzah/obsolete.rb b/spec/lib/puppet/face/huzzah/obsolete.rb new file mode 100644 index 000000000..1f717ea2f --- /dev/null +++ b/spec/lib/puppet/face/huzzah/obsolete.rb @@ -0,0 +1,6 @@ +Puppet::Face.define(:huzzah, '1.0.0') do + action :obsolete do + summary "This is an action on version 1.0.0 of the face" + when_invoked do |options| options end + end +end diff --git a/spec/lib/puppet_spec/files.rb b/spec/lib/puppet_spec/files.rb index 30fb4fc42..725bf2af9 100755 --- a/spec/lib/puppet_spec/files.rb +++ b/spec/lib/puppet_spec/files.rb @@ -1,21 +1,19 @@ require 'fileutils' require 'tempfile' +require 'pathname' # A support module for testing files. module PuppetSpec::Files # This code exists only to support tests that run as root, pretty much. # Once they have finally been eliminated this can all go... --daniel 2011-04-08 - if Puppet.features.posix? then - def self.in_tmp(path) - path =~ /^\/tmp/ or path =~ /^\/var\/folders/ - end - elsif Puppet.features.microsoft_windows? - def self.in_tmp(path) - tempdir = File.expand_path(File.join(Dir::LOCAL_APPDATA, "Temp")) - path =~ /^#{tempdir}/ + def self.in_tmp(path) + tempdir = Dir.tmpdir + + Pathname.new(path).ascend do |dir| + return true if File.identical?(tempdir, dir) end - else - fail "Help! Can't find in_tmp for this platform" + + false end def self.cleanup @@ -31,6 +29,16 @@ module PuppetSpec::Files end end + def make_absolute(path) + return path unless Puppet.features.microsoft_windows? + # REMIND UNC + return path if path =~ /^[A-Za-z]:/ + + pwd = Dir.getwd + return "#{pwd[0,2]}#{path}" if pwd.length > 2 and pwd =~ /^[A-Za-z]:/ + return "C:#{path}" + end + def tmpfile(name) # Generate a temporary file, just for the name... source = Tempfile.new(name) diff --git a/spec/shared_behaviours/file_server_terminus.rb b/spec/shared_behaviours/file_server_terminus.rb index f59169382..88ed47ebb 100755 --- a/spec/shared_behaviours/file_server_terminus.rb +++ b/spec/shared_behaviours/file_server_terminus.rb @@ -7,7 +7,7 @@ shared_examples_for "Puppet::Indirector::FileServerTerminus" do # This only works if the shared behaviour is included before # the 'before' block in the including context. before do - Puppet::Util::Cacher.expire + Puppet::FileServing::Configuration.instance_variable_set(:@configuration, nil) FileTest.stubs(:exists?).returns true FileTest.stubs(:exists?).with(Puppet[:fileserverconfig]).returns(true) diff --git a/spec/shared_behaviours/things_that_declare_options.rb b/spec/shared_behaviours/things_that_declare_options.rb index 6e7056157..ecdbfcaea 100755 --- a/spec/shared_behaviours/things_that_declare_options.rb +++ b/spec/shared_behaviours/things_that_declare_options.rb @@ -27,13 +27,12 @@ shared_examples_for "things that declare options" do thing = add_options_to do option "--foo" do - desc text description text summary text end end - thing.get_option(:foo).desc.should == text + thing.get_option(:foo).description.should == text end it "should list all the options" do @@ -44,7 +43,7 @@ shared_examples_for "things that declare options" do option "-f" option "--baz" end - thing.options.should == [:foo, :bar, :b, :q, :quux, :f, :baz] + thing.options.should == [:foo, :bar, :quux, :f, :baz] end it "should detect conflicts in long options" do @@ -147,4 +146,117 @@ shared_examples_for "things that declare options" do end end end + + describe "#default_to" do + it "should not have a default value by default" do + option = add_options_to do option "--foo" end.get_option(:foo) + option.should_not be_has_default + end + + it "should accept a block for the default value" do + option = add_options_to do + option "--foo" do + default_to do + 12 + end + end + end.get_option(:foo) + + option.should be_has_default + end + + it "should invoke the block when asked for the default value" do + invoked = false + option = add_options_to do + option "--foo" do + default_to do + invoked = true + end + end + end.get_option(:foo) + + option.should be_has_default + option.default.should be_true + invoked.should be_true + end + + it "should return the value of the block when asked for the default" do + option = add_options_to do + option "--foo" do + default_to do + 12 + end + end + end.get_option(:foo) + + option.should be_has_default + option.default.should == 12 + end + + it "should invoke the block every time the default is requested" do + option = add_options_to do + option "--foo" do + default_to do + {} + end + end + end.get_option(:foo) + + first = option.default.object_id + second = option.default.object_id + third = option.default.object_id + + first.should_not == second + first.should_not == third + second.should_not == third + end + + it "should fail if the option has a default and is required" do + expect { + add_options_to do + option "--foo" do + required + default_to do 12 end + end + end + }.to raise_error ArgumentError, /can't be optional and have a default value/ + + expect { + add_options_to do + option "--foo" do + default_to do 12 end + required + end + end + }.to raise_error ArgumentError, /can't be optional and have a default value/ + end + + it "should fail if default_to has no block" do + expect { add_options_to do option "--foo" do default_to end end }. + to raise_error ArgumentError, /default_to requires a block/ + end + + it "should fail if default_to is invoked twice" do + expect { + add_options_to do + option "--foo" do + default_to do 12 end + default_to do "fun" end + end + end + }.to raise_error ArgumentError, /already has a default value/ + end + + [ "one", "one, two", "one, *two" ].each do |input| + it "should fail if the block has the wrong arity (#{input})" do + expect { + add_options_to do + option "--foo" do + eval "default_to do |#{input}| 12 end" + end + end + }.to raise_error ArgumentError, /should not take any arguments/ + end + end + end end diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb index 19a933950..c9555157c 100755 --- a/spec/unit/application/apply_spec.rb +++ b/spec/unit/application/apply_spec.rb @@ -277,8 +277,8 @@ describe Puppet::Application::Apply do end it "should call the prerun and postrun commands on a Configurer instance" do - Puppet::Configurer.any_instance.expects(:execute_prerun_command) - Puppet::Configurer.any_instance.expects(:execute_postrun_command) + Puppet::Configurer.any_instance.expects(:execute_prerun_command).returns(true) + Puppet::Configurer.any_instance.expects(:execute_postrun_command).returns(true) expect { @apply.main }.to exit_with 0 end diff --git a/spec/unit/application/cert_spec.rb b/spec/unit/application/cert_spec.rb index 7510f0783..300234c2b 100755 --- a/spec/unit/application/cert_spec.rb +++ b/spec/unit/application/cert_spec.rb @@ -208,5 +208,15 @@ describe Puppet::Application::Cert, :'fails_on_ruby_1.9.2' => true do args.should == ["fun.example.com"] end end + + it "should print help and exit if there is no subcommand" do + args = [] + @cert_app.command_line.stubs(:args).returns(args) + @cert_app.stubs(:help).returns("I called for help!") + @cert_app.expects(:puts).with("I called for help!") + + expect { @cert_app.parse_options }.to exit_with 0 + @cert_app.subcommand.should be_nil + end end end diff --git a/spec/unit/application/device_spec.rb b/spec/unit/application/device_spec.rb index 42a62da22..f88c0c3d9 100755 --- a/spec/unit/application/device_spec.rb +++ b/spec/unit/application/device_spec.rb @@ -7,6 +7,8 @@ require 'ostruct' require 'puppet/configurer' describe Puppet::Application::Device do + include PuppetSpec::Files + before :each do @device = Puppet::Application[:device] @device.preinit @@ -264,8 +266,8 @@ describe Puppet::Application::Device do describe "for each device" do before(:each) do - Puppet[:vardir] = "/dummy" - Puppet[:confdir] = "/dummy" + Puppet[:vardir] = make_absolute("/dummy") + Puppet[:confdir] = make_absolute("/dummy") Puppet[:certname] = "certname" @device_hash = { "device1" => OpenStruct.new(:name => "device1", :url => "url", :provider => "cisco"), @@ -281,12 +283,12 @@ describe Puppet::Application::Device do end it "should set vardir to the device vardir" do - Puppet.settings.expects(:set_value).with(:vardir, "/dummy/devices/device1", :cli) + Puppet.settings.expects(:set_value).with(:vardir, make_absolute("/dummy/devices/device1"), :cli) @device.main end it "should set confdir to the device confdir" do - Puppet.settings.expects(:set_value).with(:confdir, "/dummy/devices/device1", :cli) + Puppet.settings.expects(:set_value).with(:confdir, make_absolute("/dummy/devices/device1"), :cli) @device.main end @@ -319,9 +321,9 @@ describe Puppet::Application::Device do [:vardir, :confdir].each do |setting| it "should cleanup the #{setting} setting after the run" do configurer = states('configurer').starts_as('notrun') - Puppet.settings.expects(:set_value).with(setting, "/dummy/devices/device1", :cli).when(configurer.is('notrun')) + Puppet.settings.expects(:set_value).with(setting, make_absolute("/dummy/devices/device1"), :cli).when(configurer.is('notrun')) @configurer.expects(:run).twice.then(configurer.is('run')) - Puppet.settings.expects(:set_value).with(setting, "/dummy", :cli).when(configurer.is('run')) + Puppet.settings.expects(:set_value).with(setting, make_absolute("/dummy"), :cli).when(configurer.is('run')) @device.main end diff --git a/spec/unit/application/face_base_spec.rb b/spec/unit/application/face_base_spec.rb index 0a4a86be6..bebc26210 100755 --- a/spec/unit/application/face_base_spec.rb +++ b/spec/unit/application/face_base_spec.rb @@ -55,6 +55,7 @@ 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/ end diff --git a/spec/unit/application/inspect_spec.rb b/spec/unit/application/inspect_spec.rb index 571683f37..750f25ab8 100755 --- a/spec/unit/application/inspect_spec.rb +++ b/spec/unit/application/inspect_spec.rb @@ -12,6 +12,11 @@ describe Puppet::Application::Inspect do before :each do @inspect = Puppet::Application[:inspect] + @inspect.preinit + end + + it "should operate in agent run_mode" do + @inspect.class.run_mode.name.should == :agent end describe "during setup" do @@ -98,6 +103,7 @@ describe Puppet::Application::Inspect do catalog = Puppet::Resource::Catalog.new file = Tempfile.new("foo") resource = Puppet::Resource.new(:file, file.path, :parameters => {:audit => "all"}) + file.close file.delete catalog.add_resource(resource) Puppet::Resource::Catalog::Yaml.any_instance.stubs(:find).returns(catalog) @@ -142,7 +148,7 @@ describe Puppet::Application::Inspect do @inspect.run_command end - it "should not send unreadable files" do + it "should not send unreadable files", :unless => Puppet.features.microsoft_windows? do File.open(@file, 'w') { |f| f.write('stuff') } File.chmod(0, @file) Puppet::FileBucketFile::Rest.any_instance.expects(:head).never diff --git a/spec/unit/application/master_spec.rb b/spec/unit/application/master_spec.rb index 2f6a328e2..c6df48f4d 100755 --- a/spec/unit/application/master_spec.rb +++ b/spec/unit/application/master_spec.rb @@ -5,7 +5,7 @@ require 'puppet/application/master' require 'puppet/daemon' require 'puppet/network/server' -describe Puppet::Application::Master do +describe Puppet::Application::Master, :unless => Puppet.features.microsoft_windows? do before :each do @master = Puppet::Application[:master] @daemon = stub_everything 'daemon' @@ -106,7 +106,6 @@ describe Puppet::Application::Master do end describe "during setup" do - before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:settraps) @@ -117,6 +116,12 @@ describe Puppet::Application::Master do @master.options.stubs(:[]).with(any_parameters) end + it "should abort stating that the master is not supported on Windows" do + Puppet.features.stubs(:microsoft_windows?).returns(true) + + expect { @master.setup }.to raise_error(Puppet::Error, /Puppet master is not supported on Microsoft Windows/) + end + it "should set log level to debug if --debug was passed" do @master.options.stubs(:[]).with(:debug).returns(true) @master.setup diff --git a/spec/unit/application/queue_spec.rb b/spec/unit/application/queue_spec.rb index 15e3927a1..d861383a6 100755 --- a/spec/unit/application/queue_spec.rb +++ b/spec/unit/application/queue_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' require 'puppet/application/queue' require 'puppet/indirector/catalog/queue' -describe Puppet::Application::Queue do +describe Puppet::Application::Queue, :unless => Puppet.features.microsoft_windows? do before :each do @queue = Puppet::Application[:queue] @queue.stubs(:puts) diff --git a/spec/unit/application/secret_agent_spec.rb b/spec/unit/application/secret_agent_spec.rb index eba936447..d3923406d 100755 --- a/spec/unit/application/secret_agent_spec.rb +++ b/spec/unit/application/secret_agent_spec.rb @@ -6,10 +6,12 @@ require 'puppet/indirector/report/rest' require 'tempfile' describe "Puppet::Application::Secret_agent" do + include PuppetSpec::Files + it "should retrieve and apply a catalog and submit a report" do pending "REVISIT: 2.7 changes broke this, and we want the merge published" - dirname = Dir.mktmpdir("puppetdir") + dirname = tmpdir("puppetdir") Puppet[:vardir] = dirname Puppet[:confdir] = dirname Puppet[:certname] = "foo" diff --git a/spec/unit/configurer/downloader_spec.rb b/spec/unit/configurer/downloader_spec.rb index 17b285d53..8bb6a3dc6 100755 --- a/spec/unit/configurer/downloader_spec.rb +++ b/spec/unit/configurer/downloader_spec.rb @@ -97,14 +97,15 @@ describe Puppet::Configurer::Downloader do describe "when creating the catalog to do the downloading" do before do - @dler = Puppet::Configurer::Downloader.new("foo", "/download/path", "source") + @path = make_absolute("/download/path") + @dler = Puppet::Configurer::Downloader.new("foo", @path, "source") end it "should create a catalog and add the file to it" do catalog = @dler.catalog catalog.resources.size.should == 1 catalog.resources.first.class.should == Puppet::Type::File - catalog.resources.first.name.should == "/download/path" + catalog.resources.first.name.should == @path end it "should specify that it is not managing a host catalog" do @@ -121,7 +122,7 @@ describe Puppet::Configurer::Downloader do @dler = Puppet::Configurer::Downloader.new("foo", @dl_name, source_name) end - it "should not skip downloaded resources when filtering on tags" do + it "should not skip downloaded resources when filtering on tags", :fails_on_windows => true do Puppet[:tags] = 'maytag' @dler.evaluate diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb index 0f255af76..020d1850f 100755 --- a/spec/unit/configurer_spec.rb +++ b/spec/unit/configurer_spec.rb @@ -39,16 +39,16 @@ describe Puppet::Configurer do it "should execute any pre-run command provided via the 'prerun_command' setting" do Puppet.settings[:prerun_command] = "/my/command" - Puppet::Util.expects(:execute).with { |args| args[0] == "/my/command" } + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") @agent.execute_prerun_command end it "should fail if the command fails" do Puppet.settings[:prerun_command] = "/my/command" - Puppet::Util.expects(:execute).raises Puppet::ExecutionFailure + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") - lambda { @agent.execute_prerun_command }.should raise_error(Puppet::Configurer::CommandHookError) + @agent.execute_prerun_command.should be_false end end @@ -62,16 +62,16 @@ describe Puppet::Configurer do it "should execute any post-run command provided via the 'postrun_command' setting" do Puppet.settings[:postrun_command] = "/my/command" - Puppet::Util.expects(:execute).with { |args| args[0] == "/my/command" } + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") @agent.execute_postrun_command end it "should fail if the command fails" do Puppet.settings[:postrun_command] = "/my/command" - Puppet::Util.expects(:execute).raises Puppet::ExecutionFailure + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") - lambda { @agent.execute_postrun_command }.should raise_error(Puppet::Configurer::CommandHookError) + @agent.execute_postrun_command.should be_false end end @@ -88,6 +88,9 @@ describe Puppet::Configurer do Puppet::Resource::Catalog.indirection.terminus_class = :rest Puppet::Resource::Catalog.indirection.stubs(:find).returns(@catalog) @agent.stubs(:send_report) + @agent.stubs(:save_last_run_summary) + + Puppet::Util::Log.stubs(:close_all) end it "should prepare for the run" do @@ -98,7 +101,7 @@ describe Puppet::Configurer do it "should initialize a transaction report if one is not provided" do report = Puppet::Transaction::Report.new("apply") - Puppet::Transaction::Report.expects(:new).at_least_once.returns report + Puppet::Transaction::Report.expects(:new).returns report @agent.run end @@ -128,9 +131,10 @@ describe Puppet::Configurer do it "should set the report as a log destination" do report = Puppet::Transaction::Report.new("apply") - Puppet::Transaction::Report.expects(:new).at_least_once.returns report + Puppet::Transaction::Report.expects(:new).returns report - Puppet::Util::Log.expects(:newdestination).with(report).at_least_once + Puppet::Util::Log.expects(:newdestination).with(report) + Puppet::Util::Log.expects(:close).with(report) @agent.run end @@ -180,22 +184,10 @@ describe Puppet::Configurer do it "should send the report" do report = Puppet::Transaction::Report.new("apply") - Puppet::Transaction::Report.expects(:new).at_least_once.returns(report) - @agent.expects(:send_report).with { |r, trans| r == report } - - @agent.run - end - - it "should send the transaction report with a reference to the transaction if a run was actually made" do - report = Puppet::Transaction::Report.new("apply") Puppet::Transaction::Report.expects(:new).returns(report) + @agent.expects(:send_report).with(report) - trans = stub 'transaction' - @catalog.expects(:apply).returns trans - - @agent.expects(:send_report).with { |r, t| t == trans } - - @agent.run :catalog => @catalog + @agent.run end it "should send the transaction report even if the catalog could not be retrieved" do @@ -215,12 +207,12 @@ describe Puppet::Configurer do Puppet::Transaction::Report.expects(:new).returns(report) @agent.expects(:send_report) - lambda { @agent.run }.should raise_error + @agent.run.should be_nil end it "should remove the report as a log destination when the run is finished" do report = Puppet::Transaction::Report.new("apply") - Puppet::Transaction::Report.expects(:new).at_least_once.returns(report) + Puppet::Transaction::Report.expects(:new).returns(report) @agent.run @@ -229,11 +221,100 @@ describe Puppet::Configurer do it "should return the report as the result of the run" do report = Puppet::Transaction::Report.new("apply") - Puppet::Transaction::Report.expects(:new).at_least_once.returns(report) + Puppet::Transaction::Report.expects(:new).returns(report) @agent.run.should equal(report) end + it "should send the transaction report even if the pre-run command fails" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:prerun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + @agent.expects(:send_report) + + @agent.run.should be_nil + end + + it "should include the pre-run command failure in the report" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:prerun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + + report.expects(:<<).with { |log| log.message =~ /^Could not run command from prerun_command/ } + + @agent.run.should be_nil + end + + it "should send the transaction report even if the post-run command fails" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:postrun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + @agent.expects(:send_report) + + @agent.run.should be_nil + end + + it "should include the post-run command failure in the report" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:postrun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + + report.expects(:<<).with { |log| log.message =~ /^Could not run command from postrun_command/ } + + @agent.run.should be_nil + end + + it "should execute post-run command even if the pre-run command fails" do + Puppet.settings[:prerun_command] = "/my/precommand" + Puppet.settings[:postrun_command] = "/my/postcommand" + Puppet::Util.expects(:execute).with(["/my/precommand"]).raises(Puppet::ExecutionFailure, "Failed") + Puppet::Util.expects(:execute).with(["/my/postcommand"]) + + @agent.run.should be_nil + end + + it "should finalize the report" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + report.expects(:finalize_report) + @agent.run + end + + it "should not apply the catalog if the pre-run command fails" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:prerun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + + @catalog.expects(:apply).never() + @agent.expects(:send_report) + + @agent.run.should be_nil + end + + it "should apply the catalog, send the report, and return nil if the post-run command fails" do + report = Puppet::Transaction::Report.new("apply") + Puppet::Transaction::Report.expects(:new).returns(report) + + Puppet.settings[:postrun_command] = "/my/command" + Puppet::Util.expects(:execute).with(["/my/command"]).raises(Puppet::ExecutionFailure, "Failed") + + @catalog.expects(:apply) + @agent.expects(:send_report) + + @agent.run.should be_nil + end + describe "when not using a REST terminus for catalogs" do it "should not pass any facts when retrieving the catalog" do Puppet::Resource::Catalog.indirection.terminus_class = :compiler @@ -268,12 +349,6 @@ describe Puppet::Configurer do Puppet[:lastrunfile] = tmpfile('last_run_file') @report = Puppet::Transaction::Report.new("apply") - @trans = stub 'transaction' - end - - it "should finalize the report" do - @report.expects(:finalize_report) - @configurer.send_report(@report, @trans) end it "should print a report summary if configured to do so" do @@ -282,42 +357,42 @@ describe Puppet::Configurer do @report.expects(:summary).returns "stuff" @configurer.expects(:puts).with("stuff") - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should not print a report summary if not configured to do so" do Puppet.settings[:summarize] = false @configurer.expects(:puts).never - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should save the report if reporting is enabled" do Puppet.settings[:report] = true Puppet::Transaction::Report.indirection.expects(:save).with(@report) - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should not save the report if reporting is disabled" do Puppet.settings[:report] = false Puppet::Transaction::Report.indirection.expects(:save).with(@report).never - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should save the last run summary if reporting is enabled" do Puppet.settings[:report] = true @configurer.expects(:save_last_run_summary).with(@report) - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should save the last run summary if reporting is disabled" do Puppet.settings[:report] = false @configurer.expects(:save_last_run_summary).with(@report) - @configurer.send_report(@report, nil) + @configurer.send_report(@report) end it "should log but not fail if saving the report fails" do @@ -326,7 +401,7 @@ describe Puppet::Configurer do Puppet::Transaction::Report.indirection.expects(:save).raises("whatever") Puppet.expects(:err) - lambda { @configurer.send_report(@report, nil) }.should_not raise_error + lambda { @configurer.send_report(@report) }.should_not raise_error end end @@ -505,7 +580,6 @@ describe Puppet::Configurer do Puppet.settings.stubs(:use).returns(true) @agent.stubs(:download_fact_plugins) @agent.stubs(:download_plugins) - @agent.stubs(:execute_prerun_command) @facts = {"one" => "two", "three" => "four"} end @@ -526,10 +600,5 @@ describe Puppet::Configurer do @agent.prepare({}) end - - it "should perform the pre-run commands" do - @agent.expects(:execute_prerun_command) - @agent.prepare({}) - end end end diff --git a/spec/unit/daemon_spec.rb b/spec/unit/daemon_spec.rb index e2679a966..fc43d93ad 100755 --- a/spec/unit/daemon_spec.rb +++ b/spec/unit/daemon_spec.rb @@ -28,7 +28,9 @@ describe Puppet::Daemon do end describe "when setting signal traps" do - {:INT => :stop, :TERM => :stop, :HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}.each do |signal, method| + signals = {:INT => :stop, :TERM => :stop } + signals.update({:HUP => :restart, :USR1 => :reload, :USR2 => :reopen_logs}) unless Puppet.features.microsoft_windows? + signals.each do |signal, method| it "should log and call #{method} when it receives #{signal}" do Signal.expects(:trap).with(signal).yields diff --git a/spec/unit/face/ca_spec.rb b/spec/unit/face/ca_spec.rb new file mode 100755 index 000000000..1df4d7c53 --- /dev/null +++ b/spec/unit/face/ca_spec.rb @@ -0,0 +1,355 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + +describe Puppet::Face[:ca, '0.1.0'], :unless => Puppet.features.microsoft_windows? do + include PuppetSpec::Files + + before :each do + Puppet.run_mode.stubs(:master?).returns(true) + Puppet[:ca] = true + Puppet[:ssldir] = tmpdir("face-ca-ssldir") + + Puppet::SSL::Host.ca_location = :only + Puppet[:certificate_revocation] = true + + # This is way more intimate than I want to be with the implementation, but + # there doesn't seem any other way to test this. --daniel 2011-07-18 + Puppet::SSL::CertificateAuthority.stubs(:instance).returns( + # ...and this actually does the directory creation, etc. + Puppet::SSL::CertificateAuthority.new + ) + end + + def make_certs(csr_names, crt_names) + Array(csr_names).map do |name| + Puppet::SSL::Host.new(name).generate_certificate_request + end + + Array(crt_names).map do |name| + Puppet::SSL::Host.new(name).generate + end + end + + context "#verify" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:verify) end + + it "should not explode if there is no certificate" do + expect { + subject.verify('random-host').should == { + :host => 'random-host', :valid => false, + :error => 'Could not find a certificate for random-host' + } + }.should_not raise_error + end + + it "should not explode if there is only a CSR" do + make_certs('random-host', []) + expect { + subject.verify('random-host').should == { + :host => 'random-host', :valid => false, + :error => 'Could not find a certificate for random-host' + } + }.should_not raise_error + end + + it "should verify a signed certificate" do + make_certs([], 'random-host') + subject.verify('random-host').should == { + :host => 'random-host', :valid => true + } + end + + it "should not verify a revoked certificate" do + make_certs([], 'random-host') + subject.revoke('random-host') + + expect { + subject.verify('random-host').should == { + :host => 'random-host', :valid => false, + :error => 'certificate revoked' + } + }.should_not raise_error + end + + it "should verify a revoked certificate if CRL use was turned off" do + make_certs([], 'random-host') + subject.revoke('random-host') + + Puppet[:certificate_revocation] = false + subject.verify('random-host').should == { + :host => 'random-host', :valid => true + } + end + end + + context "#fingerprint" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:fingerprint) end + + it "should have a 'digest' option" do + action.should be_option :digest + end + + it "should not explode if there is no certificate" do + expect { + subject.fingerprint('random-host').should be_nil + }.should_not raise_error + end + + it "should fingerprint a CSR" do + make_certs('random-host', []) + expect { + subject.fingerprint('random-host').should =~ /^[0-9A-F:]+$/ + }.should_not raise_error + end + + it "should fingerprint a certificate" do + make_certs([], 'random-host') + subject.fingerprint('random-host').should =~ /^[0-9A-F:]+$/ + end + + %w{md5 MD5 sha1 ShA1 SHA1 RIPEMD160 sha256 sha512}.each do |digest| + it "should fingerprint with #{digest.inspect}" do + make_certs([], 'random-host') + subject.fingerprint('random-host', :digest => digest).should =~ /^[0-9A-F:]+$/ + end + + it "should fingerprint with #{digest.to_sym} as a symbol" do + make_certs([], 'random-host') + subject.fingerprint('random-host', :digest => digest.to_sym). + should =~ /^[0-9A-F:]+$/ + end + end + end + + context "#print" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:print) end + + it "should not explode if there is no certificate" do + expect { + subject.print('random-host').should be_nil + }.should_not raise_error + end + + it "should return nothing if there is only a CSR" do + make_certs('random-host', []) + expect { + subject.print('random-host').should be_nil + }.should_not raise_error + end + + it "should return the certificate content if there is a cert" do + make_certs([], 'random-host') + text = subject.print('random-host') + text.should be_an_instance_of String + text.should =~ /^Certificate:/ + text.should =~ /Issuer: CN=Puppet CA: / + text.should =~ /Subject: CN=random-host$/ + end + end + + context "#sign" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:sign) end + + it "should not explode if there is no CSR" do + expect { + subject.sign('random-host'). + should == 'Could not find certificate request for random-host' + }.should_not raise_error + end + + it "should not explode if there is a signed cert" do + make_certs([], 'random-host') + expect { + subject.sign('random-host'). + should == 'Could not find certificate request for random-host' + }.should_not raise_error + end + + it "should sign a CSR if one exists" do + make_certs('random-host', []) + subject.sign('random-host').should be_an_instance_of Puppet::SSL::Certificate + + list = subject.list(:signed => true) + list.length.should == 1 + list.first.name.should == 'random-host' + end + end + + context "#generate" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:generate) end + + it "should generate a certificate if requested" do + subject.list(:all => true).should == [] + + subject.generate('random-host') + + list = subject.list(:signed => true) + list.length.should == 1 + list.first.name.should == 'random-host' + end + + it "should not explode if a CSR with that name already exists" do + make_certs('random-host', []) + expect { + subject.generate('random-host').should =~ /already has a certificate request/ + }.should_not raise_error + end + + it "should not explode if the certificate with that name already exists" do + make_certs([], 'random-host') + expect { + subject.generate('random-host').should =~ /already has a certificate/ + }.should_not raise_error + end + end + + context "#revoke" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:revoke) end + + it "should not explode when asked to revoke something that doesn't exist" do + expect { subject.revoke('nonesuch') }.should_not raise_error + end + + it "should let the user know what went wrong" do + subject.revoke('nonesuch').should == 'Nothing was revoked' + end + + it "should revoke a certificate" do + make_certs([], 'random-host') + found = subject.list(:all => true, :subject => 'random-host') + subject.get_action(:list).when_rendering(:console).call(found). + should =~ /^\+ random-host/ + + subject.revoke('random-host') + + found = subject.list(:all => true, :subject => 'random-host') + subject.get_action(:list).when_rendering(:console).call(found). + should =~ /^- random-host \([:0-9A-F]+\) \(certificate revoked\)/ + end + end + + context "#destroy" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:destroy) end + + it "should not explode when asked to delete something that doesn't exist" do + expect { subject.destroy('nonesuch') }.should_not raise_error + end + + it "should let the user know if nothing was deleted" do + subject.destroy('nonesuch').should == "Nothing was deleted" + end + + it "should destroy a CSR, if we have one" do + make_certs('random-host', []) + subject.list(:pending => true, :subject => 'random-host').should_not == [] + + subject.destroy('random-host') + + subject.list(:pending => true, :subject => 'random-host').should == [] + end + + it "should destroy a certificate, if we have one" do + make_certs([], 'random-host') + subject.list(:signed => true, :subject => 'random-host').should_not == [] + + subject.destroy('random-host') + + subject.list(:signed => true, :subject => 'random-host').should == [] + end + + it "should tell the user something was deleted" do + make_certs([], 'random-host') + subject.list(:signed => true, :subject => 'random-host').should_not == [] + subject.destroy('random-host'). + should == "Deleted for random-host: Puppet::SSL::Certificate, Puppet::SSL::Key" + end + end + + context "#list" do + let :action do Puppet::Face[:ca, '0.1.0'].get_action(:list) end + + context "options" do + subject { Puppet::Face[:ca, '0.1.0'].get_action(:list) } + it { should be_option :pending } + it { should be_option :signed } + it { should be_option :all } + it { should be_option :subject } + end + + context "with no hosts in CA" do + [:pending, :signed, :all].each do |type| + it "should return nothing for #{type}" do + subject.list(type => true).should == [] + end + + it "should not fail when a matcher is passed" do + expect { + subject.list(type => true, :subject => '.').should == [] + }.should_not raise_error + end + end + end + + context "with some hosts" do + csr_names = (1..3).map {|n| "csr-#{n}" } + crt_names = (1..3).map {|n| "crt-#{n}" } + all_names = csr_names + crt_names + + { + {} => csr_names, + { :pending => true } => csr_names, + + { :signed => true } => crt_names, + + { :all => true } => all_names, + { :pending => true, :signed => true } => all_names, + }.each do |input, expect| + it "should map #{input.inspect} to #{expect.inspect}" do + make_certs(csr_names, crt_names) + subject.list(input).map(&:name).should =~ expect + end + + ['', '.', '2', 'none'].each do |pattern| + filtered = expect.select {|x| Regexp.new(pattern).match(x) } + + it "should filter all hosts matching #{pattern.inspect} to #{filtered.inspect}" do + make_certs(csr_names, crt_names) + subject.list(input.merge :subject => pattern).map(&:name).should =~ filtered + end + end + end + + context "when_rendering :console" do + { [["csr1.local"], []] => '^ csr1.local ', + [[], ["crt1.local"]] => '^\+ crt1.local ', + [["csr2"], ["crt2"]] => ['^ csr2 ', '^\+ crt2 '] + }.each do |input, pattern| + it "should render #{input.inspect} to match #{pattern.inspect}" do + make_certs(*input) + text = action.when_rendering(:console).call(subject.list(:all => true)) + Array(pattern).each do |item| + text.should =~ Regexp.new(item) + end + end + end + end + end + end + + actions = %w{destroy list revoke generate sign print verify fingerprint} + actions.each do |action| + it { should be_action action } + it "should fail #{action} when not a CA" do + Puppet[:ca] = false + expect { + case subject.method(action).arity + when -1 then subject.send(action) + when -2 then subject.send(action, 'dummy') + else + raise "#{action} has arity #{subject.method(action).arity}" + end + }.should raise_error(/Not a CA/) + end + end +end diff --git a/spec/unit/face/certificate_spec.rb b/spec/unit/face/certificate_spec.rb index 0cb905b75..9291d7523 100755 --- a/spec/unit/face/certificate_spec.rb +++ b/spec/unit/face/certificate_spec.rb @@ -10,14 +10,26 @@ describe Puppet::Face[:certificate, '0.0.1'] do end it "should set the ca location when invoked" do - Puppet::SSL::Host.expects(:ca_location=).with(:foo) + Puppet::SSL::Host.expects(:ca_location=).with(:local) Puppet::SSL::Host.indirection.expects(:save) - subject.sign "hello, friend", :ca_location => :foo + subject.sign "hello, friend", :ca_location => :local end it "(#7059) should set the ca location when an inherited action is invoked" do - Puppet::SSL::Host.expects(:ca_location=).with(:foo) + Puppet::SSL::Host.expects(:ca_location=).with(:local) subject.indirection.expects(:find) - subject.find "hello, friend", :ca_location => :foo + subject.find "hello, friend", :ca_location => :local + end + + it "should validate the option as required" do + expect do + subject.find 'hello, friend' + end.to raise_exception ArgumentError, /required/i + end + + it "should validate the option as a supported value" do + expect do + subject.find 'hello, friend', :ca_location => :foo + end.to raise_exception ArgumentError, /valid values/i end end diff --git a/spec/unit/face/secret_agent_spec.rb b/spec/unit/face/secret_agent_spec.rb index a5ec01f27..2530d144d 100755 --- a/spec/unit/face/secret_agent_spec.rb +++ b/spec/unit/face/secret_agent_spec.rb @@ -5,10 +5,12 @@ require 'puppet/indirector/catalog/rest' require 'tempfile' describe Puppet::Face[:secret_agent, '0.0.1'] do + include PuppetSpec::Files + describe "#synchronize" do it "should retrieve and apply a catalog and return a report" do pending "This test doesn't work, but the code actually does - tested by LAK" - dirname = Dir.mktmpdir("puppetdir") + dirname = tmpdir("puppetdir") Puppet[:vardir] = dirname Puppet[:confdir] = dirname @catalog = Puppet::Resource::Catalog.new diff --git a/spec/unit/file_bucket/dipper_spec.rb b/spec/unit/file_bucket/dipper_spec.rb index 910b2808d..605719324 100755 --- a/spec/unit/file_bucket/dipper_spec.rb +++ b/spec/unit/file_bucket/dipper_spec.rb @@ -16,7 +16,7 @@ describe Puppet::FileBucket::Dipper do end it "should fail in an informative way when there are failures checking for the file on the server" do - @dipper = Puppet::FileBucket::Dipper.new(:Path => "/my/bucket") + @dipper = Puppet::FileBucket::Dipper.new(:Path => make_absolute("/my/bucket")) file = make_tmp_file('contents') Puppet::FileBucket::File.indirection.expects(:head).raises ArgumentError @@ -25,7 +25,7 @@ describe Puppet::FileBucket::Dipper do end it "should fail in an informative way when there are failures backing up to the server" do - @dipper = Puppet::FileBucket::Dipper.new(:Path => "/my/bucket") + @dipper = Puppet::FileBucket::Dipper.new(:Path => make_absolute("/my/bucket")) file = make_tmp_file('contents') Puppet::FileBucket::File.indirection.expects(:head).returns false @@ -34,7 +34,7 @@ describe Puppet::FileBucket::Dipper do lambda { @dipper.backup(file) }.should raise_error(Puppet::Error) end - it "should backup files to a local bucket" do + it "should backup files to a local bucket", :fails_on_windows => true do Puppet[:bucketdir] = "/non/existent/directory" file_bucket = tmpdir("bucket") @@ -91,7 +91,7 @@ describe Puppet::FileBucket::Dipper do [request1, request2].each do |r| r.server.should == 'puppetmaster' r.port.should == 31337 - r.key.should == "md5/#{checksum}#{real_path}" + r.key.should == "md5/#{checksum}/#{real_path}" end end diff --git a/spec/unit/file_bucket/file_spec.rb b/spec/unit/file_bucket/file_spec.rb index c4444ae77..ebf02438c 100755 --- a/spec/unit/file_bucket/file_spec.rb +++ b/spec/unit/file_bucket/file_spec.rb @@ -26,11 +26,17 @@ describe Puppet::FileBucket::File do it "should raise an error if changing content" do x = Puppet::FileBucket::File.new("first") - proc { x.contents = "new" }.should raise_error + expect { x.contents = "new" }.to raise_error(NoMethodError, /undefined method .contents=/) end it "should require contents to be a string" do - proc { Puppet::FileBucket::File.new(5) }.should raise_error(ArgumentError) + expect { Puppet::FileBucket::File.new(5) }.to raise_error(ArgumentError, /contents must be a String, got a Fixnum$/) + end + + it "should complain about options other than :bucket_path" do + expect { + Puppet::FileBucket::File.new('5', :crazy_option => 'should not be passed') + }.to raise_error(ArgumentError, /Unknown option\(s\): crazy_option/) end it "should set the contents appropriately" do @@ -61,7 +67,7 @@ describe Puppet::FileBucket::File do it "should reject a url-ish name with an invalid checksum" do bucket = Puppet::FileBucket::File.new(@contents) - lambda { bucket.name = "sha1/4a8ec4fa5f01b4ab1a0ab8cbccb709f0/new/path" }.should raise_error + expect { bucket.name = "sha1/4a8ec4fa5f01b4ab1a0ab8cbccb709f0/new/path" }.to raise_error(NoMethodError, /undefined method .name=/) end it "should convert the contents to PSON" do diff --git a/spec/unit/file_serving/configuration/parser_spec.rb b/spec/unit/file_serving/configuration/parser_spec.rb index 3d6b3e234..5ccfc5075 100755 --- a/spec/unit/file_serving/configuration/parser_spec.rb +++ b/spec/unit/file_serving/configuration/parser_spec.rb @@ -118,6 +118,14 @@ describe Puppet::FileServing::Configuration::Parser do @parser.parse end + it "should support inline comments" do + mock_file_content "[one]\nallow something \# will it work?\n" + + @mount.expects(:info) + @mount.expects(:allow).with("something") + @parser.parse + end + it "should tell the mount to deny any deny values from the section" do mock_file_content "[one]\ndeny something\n" diff --git a/spec/unit/file_serving/configuration_spec.rb b/spec/unit/file_serving/configuration_spec.rb index 6ee1a4f38..a1546c987 100755 --- a/spec/unit/file_serving/configuration_spec.rb +++ b/spec/unit/file_serving/configuration_spec.rb @@ -4,42 +4,31 @@ require 'spec_helper' require 'puppet/file_serving/configuration' describe Puppet::FileServing::Configuration do - it "should make :new a private method" do - proc { Puppet::FileServing::Configuration.new }.should raise_error - end - - it "should return the same configuration each time :create is called" do - Puppet::FileServing::Configuration.create.should equal(Puppet::FileServing::Configuration.create) - end - - it "should have a method for removing the current configuration instance" do - old = Puppet::FileServing::Configuration.create - Puppet::Util::Cacher.expire - Puppet::FileServing::Configuration.create.should_not equal(old) - end - - after do - Puppet::Util::Cacher.expire - end -end - -describe Puppet::FileServing::Configuration do + include PuppetSpec::Files before :each do - @path = "/path/to/configuration/file.conf" + @path = make_absolute("/path/to/configuration/file.conf") Puppet.settings.stubs(:value).with(:trace).returns(false) Puppet.settings.stubs(:value).with(:fileserverconfig).returns(@path) end after :each do - Puppet::Util::Cacher.expire + Puppet::FileServing::Configuration.instance_variable_set(:@configuration, nil) + end + + it "should make :new a private method" do + proc { Puppet::FileServing::Configuration.new }.should raise_error + end + + it "should return the same configuration each time 'configuration' is called" do + Puppet::FileServing::Configuration.configuration.should equal(Puppet::FileServing::Configuration.configuration) end describe "when initializing" do it "should work without a configuration file" do FileTest.stubs(:exists?).with(@path).returns(false) - proc { Puppet::FileServing::Configuration.create }.should_not raise_error + proc { Puppet::FileServing::Configuration.configuration }.should_not raise_error end it "should parse the configuration file if present" do @@ -47,11 +36,11 @@ describe Puppet::FileServing::Configuration do @parser = mock 'parser' @parser.expects(:parse).returns({}) Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) - Puppet::FileServing::Configuration.create + Puppet::FileServing::Configuration.configuration end it "should determine the path to the configuration file from the Puppet settings" do - Puppet::FileServing::Configuration.create + Puppet::FileServing::Configuration.configuration end end @@ -65,18 +54,18 @@ describe Puppet::FileServing::Configuration do it "should set the mount list to the results of parsing" do @parser.expects(:parse).returns("one" => mock("mount")) - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration config.mounted?("one").should be_true end it "should not raise exceptions" do @parser.expects(:parse).raises(ArgumentError) - proc { Puppet::FileServing::Configuration.create }.should_not raise_error + proc { Puppet::FileServing::Configuration.configuration }.should_not raise_error end it "should replace the existing mount list with the results of reparsing" do @parser.expects(:parse).returns("one" => mock("mount")) - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration config.mounted?("one").should be_true # Now parse again @parser.expects(:parse).returns("two" => mock('other')) @@ -88,7 +77,7 @@ describe Puppet::FileServing::Configuration do it "should not replace the mount list until the file is entirely parsed successfully" do @parser.expects(:parse).returns("one" => mock("mount")) @parser.expects(:parse).raises(ArgumentError) - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration # Now parse again, so the exception gets thrown config.send(:readconfig, false) config.mounted?("one").should be_true @@ -96,7 +85,7 @@ describe Puppet::FileServing::Configuration do it "should add modules and plugins mounts even if the file does not exist" do FileTest.expects(:exists?).returns false # the file doesn't exist - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration config.mounted?("modules").should be_true config.mounted?("plugins").should be_true end @@ -111,7 +100,7 @@ describe Puppet::FileServing::Configuration do Puppet::FileServing::Mount::Plugins.stubs(:new).returns(plugins) plugins.expects(:allow).with('*') - Puppet::FileServing::Configuration.create + Puppet::FileServing::Configuration.configuration end it "should not allow access from all to modules and plugins if the fileserver.conf provided some rules" do @@ -125,13 +114,13 @@ describe Puppet::FileServing::Configuration do Puppet::FileServing::Mount::Plugins.stubs(:new).returns(plugins) plugins.expects(:allow).with('*').never - Puppet::FileServing::Configuration.create + Puppet::FileServing::Configuration.configuration end it "should add modules and plugins mounts even if they are not returned by the parser" do @parser.expects(:parse).returns("one" => mock("mount")) FileTest.expects(:exists?).returns true # the file doesn't exist - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration config.mounted?("modules").should be_true config.mounted?("plugins").should be_true end @@ -139,13 +128,13 @@ describe Puppet::FileServing::Configuration do describe "when finding the specified mount" do it "should choose the named mount if one exists" do - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration config.expects(:mounts).returns("one" => "foo") config.find_mount("one", mock('env')).should == "foo" end it "should use the provided environment to find a matching module if the named module cannot be found" do - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration mod = mock 'module' env = mock 'environment' @@ -158,7 +147,7 @@ describe Puppet::FileServing::Configuration do end it "should return nil if there is no such named mount and no module with the same name exists" do - config = Puppet::FileServing::Configuration.create + config = Puppet::FileServing::Configuration.configuration env = mock 'environment' env.expects(:module).with("foo").returns nil @@ -171,7 +160,7 @@ describe Puppet::FileServing::Configuration do describe "when finding the mount name and relative path in a request key" do before do - @config = Puppet::FileServing::Configuration.create + @config = Puppet::FileServing::Configuration.configuration @config.stubs(:find_mount) @request = stub 'request', :key => "foo/bar/baz", :options => {}, :node => nil, :environment => mock("env") diff --git a/spec/unit/file_serving/fileset_spec.rb b/spec/unit/file_serving/fileset_spec.rb index 41810650a..aff4c91fa 100755 --- a/spec/unit/file_serving/fileset_spec.rb +++ b/spec/unit/file_serving/fileset_spec.rb @@ -4,6 +4,12 @@ require 'spec_helper' require 'puppet/file_serving/fileset' describe Puppet::FileServing::Fileset, " when initializing" do + include PuppetSpec::Files + + before :each do + @somefile = make_absolute("/some/file") + end + it "should require a path" do proc { Puppet::FileServing::Fileset.new }.should raise_error(ArgumentError) end @@ -13,83 +19,82 @@ describe Puppet::FileServing::Fileset, " when initializing" do end it "should not fail if the path is fully qualified, with a trailing separator" do - path = "/some/path/with/trailing/separator" - path_with_separator = "#{path}#{File::SEPARATOR}" - File.stubs(:lstat).with(path).returns stub('stat') + path_with_separator = "#{@somefile}#{File::SEPARATOR}" + File.stubs(:lstat).with(@somefile).returns stub('stat') fileset = Puppet::FileServing::Fileset.new(path_with_separator) - fileset.path.should == path + fileset.path.should == @somefile end it "should not fail if the path is just the file separator" do - path = File::SEPARATOR + path = make_absolute(File::SEPARATOR) File.stubs(:lstat).with(path).returns stub('stat') fileset = Puppet::FileServing::Fileset.new(path) fileset.path.should == path end it "should fail if its path does not exist" do - File.expects(:lstat).with("/some/file").returns nil - proc { Puppet::FileServing::Fileset.new("/some/file") }.should raise_error(ArgumentError) + File.expects(:lstat).with(@somefile).returns nil + proc { Puppet::FileServing::Fileset.new(@somefile) }.should raise_error(ArgumentError) end it "should accept a 'recurse' option" do - File.expects(:lstat).with("/some/file").returns stub("stat") - set = Puppet::FileServing::Fileset.new("/some/file", :recurse => true) + File.expects(:lstat).with(@somefile).returns stub("stat") + set = Puppet::FileServing::Fileset.new(@somefile, :recurse => true) set.recurse.should be_true end it "should accept a 'recurselimit' option" do - File.expects(:lstat).with("/some/file").returns stub("stat") - set = Puppet::FileServing::Fileset.new("/some/file", :recurselimit => 3) + File.expects(:lstat).with(@somefile).returns stub("stat") + set = Puppet::FileServing::Fileset.new(@somefile, :recurselimit => 3) set.recurselimit.should == 3 end it "should accept an 'ignore' option" do - File.expects(:lstat).with("/some/file").returns stub("stat") - set = Puppet::FileServing::Fileset.new("/some/file", :ignore => ".svn") + File.expects(:lstat).with(@somefile).returns stub("stat") + set = Puppet::FileServing::Fileset.new(@somefile, :ignore => ".svn") set.ignore.should == [".svn"] end it "should accept a 'links' option" do - File.expects(:lstat).with("/some/file").returns stub("stat") - set = Puppet::FileServing::Fileset.new("/some/file", :links => :manage) + File.expects(:lstat).with(@somefile).returns stub("stat") + set = Puppet::FileServing::Fileset.new(@somefile, :links => :manage) set.links.should == :manage end it "should accept a 'checksum_type' option" do - File.expects(:lstat).with("/some/file").returns stub("stat") - set = Puppet::FileServing::Fileset.new("/some/file", :checksum_type => :test) + File.expects(:lstat).with(@somefile).returns stub("stat") + set = Puppet::FileServing::Fileset.new(@somefile, :checksum_type => :test) set.checksum_type.should == :test end it "should fail if 'links' is set to anything other than :manage or :follow" do - proc { Puppet::FileServing::Fileset.new("/some/file", :links => :whatever) }.should raise_error(ArgumentError) + proc { Puppet::FileServing::Fileset.new(@somefile, :links => :whatever) }.should raise_error(ArgumentError) end it "should default to 'false' for recurse" do - File.expects(:lstat).with("/some/file").returns stub("stat") - Puppet::FileServing::Fileset.new("/some/file").recurse.should == false + File.expects(:lstat).with(@somefile).returns stub("stat") + Puppet::FileServing::Fileset.new(@somefile).recurse.should == false end it "should default to :infinite for recurselimit" do - File.expects(:lstat).with("/some/file").returns stub("stat") - Puppet::FileServing::Fileset.new("/some/file").recurselimit.should == :infinite + File.expects(:lstat).with(@somefile).returns stub("stat") + Puppet::FileServing::Fileset.new(@somefile).recurselimit.should == :infinite end it "should default to an empty ignore list" do - File.expects(:lstat).with("/some/file").returns stub("stat") - Puppet::FileServing::Fileset.new("/some/file").ignore.should == [] + File.expects(:lstat).with(@somefile).returns stub("stat") + Puppet::FileServing::Fileset.new(@somefile).ignore.should == [] end it "should default to :manage for links" do - File.expects(:lstat).with("/some/file").returns stub("stat") - Puppet::FileServing::Fileset.new("/some/file").links.should == :manage + File.expects(:lstat).with(@somefile).returns stub("stat") + Puppet::FileServing::Fileset.new(@somefile).links.should == :manage end it "should support using an Indirector Request for its options" do - File.expects(:lstat).with("/some/file").returns stub("stat") + File.expects(:lstat).with(@somefile).returns stub("stat") request = Puppet::Indirector::Request.new(:file_serving, :find, "foo") - lambda { Puppet::FileServing::Fileset.new("/some/file", request) }.should_not raise_error + lambda { Puppet::FileServing::Fileset.new(@somefile, request) }.should_not raise_error end describe "using an indirector request" do @@ -97,40 +102,43 @@ describe Puppet::FileServing::Fileset, " when initializing" do File.stubs(:lstat).returns stub("stat") @values = {:links => :manage, :ignore => %w{a b}, :recurse => true, :recurselimit => 1234} @request = Puppet::Indirector::Request.new(:file_serving, :find, "foo") + @myfile = make_absolute("/my/file") end [:recurse, :recurselimit, :ignore, :links].each do |option| it "should pass :recurse, :recurselimit, :ignore, and :links settings on to the fileset if present" do @request.stubs(:options).returns(option => @values[option]) - Puppet::FileServing::Fileset.new("/my/file", @request).send(option).should == @values[option] + Puppet::FileServing::Fileset.new(@myfile, @request).send(option).should == @values[option] end it "should pass :recurse, :recurselimit, :ignore, and :links settings on to the fileset if present with the keys stored as strings" do @request.stubs(:options).returns(option.to_s => @values[option]) - Puppet::FileServing::Fileset.new("/my/file", @request).send(option).should == @values[option] + Puppet::FileServing::Fileset.new(@myfile, @request).send(option).should == @values[option] end end it "should convert the integer as a string to their integer counterpart when setting options" do @request.stubs(:options).returns(:recurselimit => "1234") - Puppet::FileServing::Fileset.new("/my/file", @request).recurselimit.should == 1234 + Puppet::FileServing::Fileset.new(@myfile, @request).recurselimit.should == 1234 end it "should convert the string 'true' to the boolean true when setting options" do @request.stubs(:options).returns(:recurse => "true") - Puppet::FileServing::Fileset.new("/my/file", @request).recurse.should == true + Puppet::FileServing::Fileset.new(@myfile, @request).recurse.should == true end it "should convert the string 'false' to the boolean false when setting options" do @request.stubs(:options).returns(:recurse => "false") - Puppet::FileServing::Fileset.new("/my/file", @request).recurse.should == false + Puppet::FileServing::Fileset.new(@myfile, @request).recurse.should == false end end end describe Puppet::FileServing::Fileset, " when determining whether to recurse" do + include PuppetSpec::Files + before do - @path = "/my/path" + @path = make_absolute("/my/path") File.expects(:lstat).with(@path).returns stub("stat") @fileset = Puppet::FileServing::Fileset.new(@path) end @@ -166,8 +174,10 @@ describe Puppet::FileServing::Fileset, " when determining whether to recurse" do end describe Puppet::FileServing::Fileset, " when recursing" do + include PuppetSpec::Files + before do - @path = "/my/path" + @path = make_absolute("/my/path") File.expects(:lstat).with(@path).returns stub("stat", :directory? => true) @fileset = Puppet::FileServing::Fileset.new(@path) @@ -257,7 +267,7 @@ describe Puppet::FileServing::Fileset, " when recursing" do end it "should succeed when paths have regexp significant characters" do - @path = "/my/path/rV1x2DafFr0R6tGG+1bbk++++TM" + @path = make_absolute("/my/path/rV1x2DafFr0R6tGG+1bbk++++TM") File.expects(:lstat).with(@path).returns stub("stat", :directory? => true) @fileset = Puppet::FileServing::Fileset.new(@path) mock_dir_structure(@path) @@ -267,8 +277,10 @@ describe Puppet::FileServing::Fileset, " when recursing" do end describe Puppet::FileServing::Fileset, " when following links that point to missing files" do + include PuppetSpec::Files + before do - @path = "/my/path" + @path = make_absolute("/my/path") File.expects(:lstat).with(@path).returns stub("stat", :directory? => true) @fileset = Puppet::FileServing::Fileset.new(@path) @fileset.links = :follow @@ -291,8 +303,10 @@ describe Puppet::FileServing::Fileset, " when following links that point to miss end describe Puppet::FileServing::Fileset, " when ignoring" do + include PuppetSpec::Files + before do - @path = "/my/path" + @path = make_absolute("/my/path") File.expects(:lstat).with(@path).returns stub("stat", :directory? => true) @fileset = Puppet::FileServing::Fileset.new(@path) end @@ -318,8 +332,10 @@ describe Puppet::FileServing::Fileset, " when ignoring" do end describe Puppet::FileServing::Fileset, "when merging other filesets" do + include PuppetSpec::Files + before do - @paths = %w{/first/path /second/path /third/path} + @paths = [make_absolute("/first/path"), make_absolute("/second/path"), make_absolute("/third/path")] File.stubs(:lstat).returns stub("stat", :directory? => false) @filesets = @paths.collect do |path| @@ -331,32 +347,32 @@ describe Puppet::FileServing::Fileset, "when merging other filesets" do end it "should return a hash of all files in each fileset with the value being the base path" do - Dir.expects(:entries).with("/first/path").returns(%w{one uno}) - Dir.expects(:entries).with("/second/path").returns(%w{two dos}) - Dir.expects(:entries).with("/third/path").returns(%w{three tres}) + Dir.expects(:entries).with(make_absolute("/first/path")).returns(%w{one uno}) + Dir.expects(:entries).with(make_absolute("/second/path")).returns(%w{two dos}) + Dir.expects(:entries).with(make_absolute("/third/path")).returns(%w{three tres}) Puppet::FileServing::Fileset.merge(*@filesets).should == { - "." => "/first/path", - "one" => "/first/path", - "uno" => "/first/path", - "two" => "/second/path", - "dos" => "/second/path", - "three" => "/third/path", - "tres" => "/third/path", + "." => make_absolute("/first/path"), + "one" => make_absolute("/first/path"), + "uno" => make_absolute("/first/path"), + "two" => make_absolute("/second/path"), + "dos" => make_absolute("/second/path"), + "three" => make_absolute("/third/path"), + "tres" => make_absolute("/third/path"), } end it "should include the base directory from the first fileset" do - Dir.expects(:entries).with("/first/path").returns(%w{one}) - Dir.expects(:entries).with("/second/path").returns(%w{two}) + Dir.expects(:entries).with(make_absolute("/first/path")).returns(%w{one}) + Dir.expects(:entries).with(make_absolute("/second/path")).returns(%w{two}) - Puppet::FileServing::Fileset.merge(*@filesets)["."].should == "/first/path" + Puppet::FileServing::Fileset.merge(*@filesets)["."].should == make_absolute("/first/path") end it "should use the base path of the first found file when relative file paths conflict" do - Dir.expects(:entries).with("/first/path").returns(%w{one}) - Dir.expects(:entries).with("/second/path").returns(%w{one}) + Dir.expects(:entries).with(make_absolute("/first/path")).returns(%w{one}) + Dir.expects(:entries).with(make_absolute("/second/path")).returns(%w{one}) - Puppet::FileServing::Fileset.merge(*@filesets)["one"].should == "/first/path" + Puppet::FileServing::Fileset.merge(*@filesets)["one"].should == make_absolute("/first/path") end end diff --git a/spec/unit/file_serving/mount/file_spec.rb b/spec/unit/file_serving/mount/file_spec.rb index 70c804abd..1ee004c10 100755 --- a/spec/unit/file_serving/mount/file_spec.rb +++ b/spec/unit/file_serving/mount/file_spec.rb @@ -10,12 +10,6 @@ module FileServingMountTesting end describe Puppet::FileServing::Mount::File do - it "should provide a method for clearing its cached host information" do - old = Puppet::FileServing::Mount::File.localmap - Puppet::Util::Cacher.expire - Puppet::FileServing::Mount::File.localmap.should_not equal(old) - end - it "should be invalid if it does not have a path" do lambda { Puppet::FileServing::Mount::File.new("foo").validate }.should raise_error(ArgumentError) end @@ -27,169 +21,169 @@ describe Puppet::FileServing::Mount::File do mount.path = "/foo" lambda { mount.validate }.should_not raise_error(ArgumentError) end -end - -describe Puppet::FileServing::Mount::File, " when setting the path" do - before do - @mount = Puppet::FileServing::Mount::File.new("test") - @dir = "/this/path/does/not/exist" - end - - it "should fail if the path is not a directory" do - FileTest.expects(:directory?).returns(false) - proc { @mount.path = @dir }.should raise_error(ArgumentError) - end - - it "should fail if the path is not readable" do - FileTest.expects(:directory?).returns(true) - FileTest.expects(:readable?).returns(false) - proc { @mount.path = @dir }.should raise_error(ArgumentError) - end -end - -describe Puppet::FileServing::Mount::File, " when substituting hostnames and ip addresses into file paths" do - include FileServingMountTesting - - before do - FileTest.stubs(:directory?).returns(true) - FileTest.stubs(:readable?).returns(true) - @mount = Puppet::FileServing::Mount::File.new("test") - @host = "host.domain.com" - end - - it "should replace incidences of %h in the path with the client's short name" do - @mount.path = "/dir/%h/yay" - @mount.path(@host).should == "/dir/host/yay" - end - - it "should replace incidences of %H in the path with the client's fully qualified name" do - @mount.path = "/dir/%H/yay" - @mount.path(@host).should == "/dir/host.domain.com/yay" - end - - it "should replace incidences of %d in the path with the client's domain name" do - @mount.path = "/dir/%d/yay" - @mount.path(@host).should == "/dir/domain.com/yay" - end - - it "should perform all necessary replacements" do - @mount.path = "/%h/%d/%H" - @mount.path(@host).should == "/host/domain.com/host.domain.com" - end - - it "should use local host information if no client data is provided" do - stub_facter("myhost.mydomain.com") - @mount.path = "/%h/%d/%H" - @mount.path.should == "/myhost/mydomain.com/myhost.mydomain.com" - end - - after do - Puppet::Util::Cacher.expire - end -end - -describe Puppet::FileServing::Mount::File, "when determining the complete file path" do - include FileServingMountTesting - - before do - FileTest.stubs(:exist?).returns(true) - FileTest.stubs(:directory?).returns(true) - FileTest.stubs(:readable?).returns(true) - @mount = Puppet::FileServing::Mount::File.new("test") - @mount.path = "/mount" - stub_facter("myhost.mydomain.com") - @host = "host.domain.com" - end - - it "should return nil if the file is absent" do - FileTest.stubs(:exist?).returns(false) - @mount.complete_path("/my/path", nil).should be_nil - end - - it "should write a log message if the file is absent" do - FileTest.stubs(:exist?).returns(false) - - Puppet.expects(:info).with("File does not exist or is not accessible: /mount/my/path") - - @mount.complete_path("/my/path", nil) - end - - it "should return the file path if the file is present" do - FileTest.stubs(:exist?).with("/my/path").returns(true) - @mount.complete_path("/my/path", nil).should == "/mount/my/path" - end - - it "should treat a nil file name as the path to the mount itself" do - FileTest.stubs(:exist?).returns(true) - @mount.complete_path(nil, nil).should == "/mount" - end - - it "should use the client host name if provided in the options" do - @mount.path = "/mount/%h" - @mount.complete_path("/my/path", @host).should == "/mount/host/my/path" - end - - it "should perform replacements on the base path" do - @mount.path = "/blah/%h" - @mount.complete_path("/my/stuff", @host).should == "/blah/host/my/stuff" - end - - it "should not perform replacements on the per-file path" do - @mount.path = "/blah" - @mount.complete_path("/%h/stuff", @host).should == "/blah/%h/stuff" - end - - it "should look for files relative to its base directory" do - @mount.complete_path("/my/stuff", @host).should == "/mount/my/stuff" - end -end - -describe Puppet::FileServing::Mount::File, "when finding files" do - include FileServingMountTesting - - before do - FileTest.stubs(:exist?).returns(true) - FileTest.stubs(:directory?).returns(true) - FileTest.stubs(:readable?).returns(true) - @mount = Puppet::FileServing::Mount::File.new("test") - @mount.path = "/mount" - stub_facter("myhost.mydomain.com") - @host = "host.domain.com" - - @request = stub 'request', :node => "foo" - end - - it "should return the results of the complete file path" do - FileTest.stubs(:exist?).returns(false) - @mount.expects(:complete_path).with("/my/path", "foo").returns "eh" - @mount.find("/my/path", @request).should == "eh" - end -end - -describe Puppet::FileServing::Mount::File, "when searching for files" do - include FileServingMountTesting - - before do - FileTest.stubs(:exist?).returns(true) - FileTest.stubs(:directory?).returns(true) - FileTest.stubs(:readable?).returns(true) - @mount = Puppet::FileServing::Mount::File.new("test") - @mount.path = "/mount" - stub_facter("myhost.mydomain.com") - @host = "host.domain.com" - - @request = stub 'request', :node => "foo" - end - - it "should return the results of the complete file path as an array" do - FileTest.stubs(:exist?).returns(false) - @mount.expects(:complete_path).with("/my/path", "foo").returns "eh" - @mount.search("/my/path", @request).should == ["eh"] - end - it "should return nil if the complete path is nil" do - FileTest.stubs(:exist?).returns(false) - @mount.expects(:complete_path).with("/my/path", "foo").returns nil - @mount.search("/my/path", @request).should be_nil + describe "when setting the path" do + before do + @mount = Puppet::FileServing::Mount::File.new("test") + @dir = "/this/path/does/not/exist" + end + + it "should fail if the path is not a directory" do + FileTest.expects(:directory?).returns(false) + proc { @mount.path = @dir }.should raise_error(ArgumentError) + end + + it "should fail if the path is not readable" do + FileTest.expects(:directory?).returns(true) + FileTest.expects(:readable?).returns(false) + proc { @mount.path = @dir }.should raise_error(ArgumentError) + end + end + + describe "when substituting hostnames and ip addresses into file paths" do + include FileServingMountTesting + + before do + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:readable?).returns(true) + @mount = Puppet::FileServing::Mount::File.new("test") + @host = "host.domain.com" + end + + after :each do + Puppet::FileServing::Mount::File.instance_variable_set(:@localmap, nil) + end + + it "should replace incidences of %h in the path with the client's short name" do + @mount.path = "/dir/%h/yay" + @mount.path(@host).should == "/dir/host/yay" + end + + it "should replace incidences of %H in the path with the client's fully qualified name" do + @mount.path = "/dir/%H/yay" + @mount.path(@host).should == "/dir/host.domain.com/yay" + end + + it "should replace incidences of %d in the path with the client's domain name" do + @mount.path = "/dir/%d/yay" + @mount.path(@host).should == "/dir/domain.com/yay" + end + + it "should perform all necessary replacements" do + @mount.path = "/%h/%d/%H" + @mount.path(@host).should == "/host/domain.com/host.domain.com" + end + + it "should use local host information if no client data is provided" do + stub_facter("myhost.mydomain.com") + @mount.path = "/%h/%d/%H" + @mount.path.should == "/myhost/mydomain.com/myhost.mydomain.com" + end + end + + describe "when determining the complete file path" do + include FileServingMountTesting + + before do + FileTest.stubs(:exist?).returns(true) + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:readable?).returns(true) + @mount = Puppet::FileServing::Mount::File.new("test") + @mount.path = "/mount" + stub_facter("myhost.mydomain.com") + @host = "host.domain.com" + end + + it "should return nil if the file is absent" do + FileTest.stubs(:exist?).returns(false) + @mount.complete_path("/my/path", nil).should be_nil + end + + it "should write a log message if the file is absent" do + FileTest.stubs(:exist?).returns(false) + + Puppet.expects(:info).with("File does not exist or is not accessible: /mount/my/path") + + @mount.complete_path("/my/path", nil) + end + + it "should return the file path if the file is present" do + FileTest.stubs(:exist?).with("/my/path").returns(true) + @mount.complete_path("/my/path", nil).should == "/mount/my/path" + end + + it "should treat a nil file name as the path to the mount itself" do + FileTest.stubs(:exist?).returns(true) + @mount.complete_path(nil, nil).should == "/mount" + end + + it "should use the client host name if provided in the options" do + @mount.path = "/mount/%h" + @mount.complete_path("/my/path", @host).should == "/mount/host/my/path" + end + + it "should perform replacements on the base path" do + @mount.path = "/blah/%h" + @mount.complete_path("/my/stuff", @host).should == "/blah/host/my/stuff" + end + + it "should not perform replacements on the per-file path" do + @mount.path = "/blah" + @mount.complete_path("/%h/stuff", @host).should == "/blah/%h/stuff" + end + + it "should look for files relative to its base directory" do + @mount.complete_path("/my/stuff", @host).should == "/mount/my/stuff" + end + end + + describe "when finding files" do + include FileServingMountTesting + + before do + FileTest.stubs(:exist?).returns(true) + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:readable?).returns(true) + @mount = Puppet::FileServing::Mount::File.new("test") + @mount.path = "/mount" + stub_facter("myhost.mydomain.com") + @host = "host.domain.com" + + @request = stub 'request', :node => "foo" + end + + it "should return the results of the complete file path" do + FileTest.stubs(:exist?).returns(false) + @mount.expects(:complete_path).with("/my/path", "foo").returns "eh" + @mount.find("/my/path", @request).should == "eh" + end + end + + describe "when searching for files" do + include FileServingMountTesting + + before do + FileTest.stubs(:exist?).returns(true) + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:readable?).returns(true) + @mount = Puppet::FileServing::Mount::File.new("test") + @mount.path = "/mount" + stub_facter("myhost.mydomain.com") + @host = "host.domain.com" + + @request = stub 'request', :node => "foo" + end + + it "should return the results of the complete file path as an array" do + FileTest.stubs(:exist?).returns(false) + @mount.expects(:complete_path).with("/my/path", "foo").returns "eh" + @mount.search("/my/path", @request).should == ["eh"] + end + + it "should return nil if the complete path is nil" do + FileTest.stubs(:exist?).returns(false) + @mount.expects(:complete_path).with("/my/path", "foo").returns nil + @mount.search("/my/path", @request).should be_nil + end end end diff --git a/spec/unit/indirector/certificate/rest_spec.rb b/spec/unit/indirector/certificate/rest_spec.rb index 21e10e316..870d9e437 100755 --- a/spec/unit/indirector/certificate/rest_spec.rb +++ b/spec/unit/indirector/certificate/rest_spec.rb @@ -47,6 +47,7 @@ rn/G response = stub 'response', :code => "200", :body => cert_string response.stubs(:[]).with('content-type').returns "text/plain" response.stubs(:[]).with('content-encoding') + network.stubs(:verify_callback=) network.expects(:get).returns response request = Puppet::Indirector::Request.new(:certificate, :find, "foo.com") diff --git a/spec/unit/indirector/certificate_request/ca_spec.rb b/spec/unit/indirector/certificate_request/ca_spec.rb index ebd64a2fb..36628df9d 100755 --- a/spec/unit/indirector/certificate_request/ca_spec.rb +++ b/spec/unit/indirector/certificate_request/ca_spec.rb @@ -10,7 +10,7 @@ require 'puppet/sslcertificates' require 'puppet/sslcertificates/ca' require 'puppet/indirector/certificate_request/ca' -describe Puppet::SSL::CertificateRequest::Ca do +describe Puppet::SSL::CertificateRequest::Ca, :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files before :each do diff --git a/spec/unit/indirector/certificate_status/file_spec.rb b/spec/unit/indirector/certificate_status/file_spec.rb index ae03aa9cb..c5d4e283f 100755 --- a/spec/unit/indirector/certificate_status/file_spec.rb +++ b/spec/unit/indirector/certificate_status/file_spec.rb @@ -4,9 +4,13 @@ require 'puppet/ssl/host' require 'puppet/indirector/certificate_status' require 'tempfile' -describe "Puppet::Indirector::CertificateStatus::File" do +describe "Puppet::Indirector::CertificateStatus::File", :fails_on_windows => true do include PuppetSpec::Files + before :all do + Puppet::SSL::Host.configure_indirection(:file) + end + before do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true @terminus = Puppet::SSL::Host.indirection.terminus(:file) diff --git a/spec/unit/indirector/face_spec.rb b/spec/unit/indirector/face_spec.rb index 943ff7991..8e324f019 100755 --- a/spec/unit/indirector/face_spec.rb +++ b/spec/unit/indirector/face_spec.rb @@ -12,6 +12,8 @@ describe Puppet::Indirector::Face do instance end + it { should be_option :extra } + it "should be able to return a list of indirections" do Puppet::Indirector::Face.indirections.should be_include("catalog") end @@ -48,7 +50,7 @@ describe Puppet::Indirector::Face do end it "should forward passed options" do subject.indirection.expects(method).with(:test, {'one'=>'1'}) - subject.send(method, :test, {'one'=>'1'}) + subject.send(method, :test, :extra => {'one'=>'1'}) end end diff --git a/spec/unit/indirector/file_bucket_file/file_spec.rb b/spec/unit/indirector/file_bucket_file/file_spec.rb index e0612cb21..808da17d8 100755 --- a/spec/unit/indirector/file_bucket_file/file_spec.rb +++ b/spec/unit/indirector/file_bucket_file/file_spec.rb @@ -111,7 +111,7 @@ describe Puppet::FileBucketFile::File do end end - describe "when diffing files" do + describe "when diffing files", :unless => Puppet.features.microsoft_windows? do it "should generate an empty string if there is no diff" do checksum = save_bucket_file("I'm the contents of a file") Puppet::FileBucket::File.indirection.find("md5/#{checksum}", :diff_with => checksum).should == '' @@ -243,11 +243,11 @@ HERE describe "when verifying identical files" do before do # this is the default from spec_helper, but it keeps getting reset at odd times - Puppet[:bucketdir] = "/dev/null/bucket" + Puppet[:bucketdir] = make_absolute("/dev/null/bucket") @digest = "4a8ec4fa5f01b4ab1a0ab8cbccb709f0" @checksum = "{md5}4a8ec4fa5f01b4ab1a0ab8cbccb709f0" - @dir = '/dev/null/bucket/4/a/8/e/c/4/f/a/4a8ec4fa5f01b4ab1a0ab8cbccb709f0' + @dir = make_absolute('/dev/null/bucket/4/a/8/e/c/4/f/a/4a8ec4fa5f01b4ab1a0ab8cbccb709f0') @contents = "file contents" diff --git a/spec/unit/indirector/file_server_spec.rb b/spec/unit/indirector/file_server_spec.rb index 6df715fb1..96fe101d5 100755 --- a/spec/unit/indirector/file_server_spec.rb +++ b/spec/unit/indirector/file_server_spec.rb @@ -27,7 +27,7 @@ describe Puppet::Indirector::FileServer do @uri = "puppet://host/my/local/file" @configuration = mock 'configuration' - Puppet::FileServing::Configuration.stubs(:create).returns(@configuration) + Puppet::FileServing::Configuration.stubs(:configuration).returns(@configuration) @request = Puppet::Indirector::Request.new(:myind, :mymethod, @uri, :environment => "myenv") end diff --git a/spec/unit/indirector/indirection_spec.rb b/spec/unit/indirector/indirection_spec.rb index 4bbc855b1..c33fdf165 100755 --- a/spec/unit/indirector/indirection_spec.rb +++ b/spec/unit/indirector/indirection_spec.rb @@ -102,9 +102,6 @@ shared_examples_for "Delegation Authorizer" do end describe Puppet::Indirector::Indirection do - after do - Puppet::Util::Cacher.expire - end describe "when initializing" do # (LAK) I've no idea how to test this, really. it "should store a reference to itself before it consumes its options" do @@ -643,7 +640,6 @@ describe Puppet::Indirector::Indirection do after :each do @indirection.delete - Puppet::Util::Cacher.expire end end diff --git a/spec/unit/indirector/report/processor_spec.rb b/spec/unit/indirector/report/processor_spec.rb index bafbe6ee7..fbc70a104 100755 --- a/spec/unit/indirector/report/processor_spec.rb +++ b/spec/unit/indirector/report/processor_spec.rb @@ -25,9 +25,11 @@ describe Puppet::Transaction::Report::Processor, " when saving a report" do it "should not process the report if reports are set to 'none'" do Puppet::Reports.expects(:report).never - Puppet.settings.expects(:value).with(:reports).returns("none") + Puppet[:reports] = 'none' - request = stub 'request', :instance => mock("report") + request = Puppet::Indirector::Request.new(:indirection_name, :head, "key") + report = Puppet::Transaction::Report.new('apply') + request.instance = report @reporter.save(request) end @@ -40,14 +42,14 @@ end describe Puppet::Transaction::Report::Processor, " when processing a report" do before do - Puppet.settings.stubs(:value).with(:reports).returns("one") + Puppet[:reports] = "one" Puppet.settings.stubs(:use) @reporter = Puppet::Transaction::Report::Processor.new @report_type = mock 'one' @dup_report = mock 'dupe report' @dup_report.stubs(:process) - @report = mock 'report' + @report = Puppet::Transaction::Report.new('apply') @report.expects(:dup).returns(@dup_report) @request = stub 'request', :instance => @report @@ -74,7 +76,7 @@ describe Puppet::Transaction::Report::Processor, " when processing a report" do end it "should not raise exceptions" do - Puppet.settings.stubs(:value).with(:trace).returns(false) + Puppet[:trace] = false @dup_report.expects(:process).raises(ArgumentError) proc { @reporter.save(@request) }.should_not raise_error end diff --git a/spec/unit/indirector/request_spec.rb b/spec/unit/indirector/request_spec.rb index 87b9af438..059357869 100755 --- a/spec/unit/indirector/request_spec.rb +++ b/spec/unit/indirector/request_spec.rb @@ -2,8 +2,16 @@ require 'spec_helper' require 'matchers/json' require 'puppet/indirector/request' +require 'puppet/util/pson' describe Puppet::Indirector::Request do + + describe "when registering the document type" do + it "should register its document type with JSON" do + PSON.registered_document_types["IndirectorRequest"].should equal(Puppet::Indirector::Request) + end + end + describe "when initializing" do it "should require an indirection name, a key, and a method" do lambda { Puppet::Indirector::Request.new }.should raise_error(ArgumentError) @@ -301,4 +309,99 @@ describe Puppet::Indirector::Request do lambda { @request.query_string }.should raise_error(ArgumentError) end end + + describe "when converting to json" do + before do + @request = Puppet::Indirector::Request.new(:facts, :find, "foo") + end + + it "should produce a hash with the document_type set to 'request'" do + @request.should set_json_document_type_to("IndirectorRequest") + end + + it "should set the 'key'" do + @request.should set_json_attribute("key").to("foo") + end + + it "should include an attribute for its indirection name" do + @request.should set_json_attribute("type").to("facts") + end + + it "should include a 'method' attribute set to its method" do + @request.should set_json_attribute("method").to("find") + end + + it "should add all attributes under the 'attributes' attribute" do + @request.ip = "127.0.0.1" + @request.should set_json_attribute("attributes", "ip").to("127.0.0.1") + end + + it "should add all options under the 'attributes' attribute" do + @request.options["opt"] = "value" + PSON.parse(@request.to_pson)["data"]['attributes']['opt'].should == "value" + end + + it "should include the instance if provided" do + facts = Puppet::Node::Facts.new("foo") + @request.instance = facts + PSON.parse(@request.to_pson)["data"]['instance'].should be_instance_of(Hash) + end + end + + describe "when converting from json" do + before do + @request = Puppet::Indirector::Request.new(:facts, :find, "foo") + @klass = Puppet::Indirector::Request + @format = Puppet::Network::FormatHandler.format('pson') + end + + def from_json(json) + @format.intern(Puppet::Indirector::Request, json) + end + + it "should set the 'key'" do + from_json(@request.to_pson).key.should == "foo" + end + + it "should fail if no key is provided" do + json = PSON.parse(@request.to_pson) + json['data'].delete("key") + lambda { from_json(json.to_pson) }.should raise_error(ArgumentError) + end + + it "should set its indirector name" do + from_json(@request.to_pson).indirection_name.should == :facts + end + + it "should fail if no type is provided" do + json = PSON.parse(@request.to_pson) + json['data'].delete("type") + lambda { from_json(json.to_pson) }.should raise_error(ArgumentError) + end + + it "should set its method" do + from_json(@request.to_pson).method.should == "find" + end + + it "should fail if no method is provided" do + json = PSON.parse(@request.to_pson) + json['data'].delete("method") + lambda { from_json(json.to_pson) }.should raise_error(ArgumentError) + end + + it "should initialize with all attributes and options" do + @request.ip = "127.0.0.1" + @request.options["opt"] = "value" + result = from_json(@request.to_pson) + result.options[:opt].should == "value" + result.ip.should == "127.0.0.1" + end + + it "should set its instance as an instance if one is provided" do + facts = Puppet::Node::Facts.new("foo") + @request.instance = facts + result = from_json(@request.to_pson) + result.instance.should be_instance_of(Puppet::Node::Facts) + end + end end diff --git a/spec/unit/indirector/resource/ral_spec.rb b/spec/unit/indirector/resource/ral_spec.rb index cf746cb0c..e38745f05 100755 --- a/spec/unit/indirector/resource/ral_spec.rb +++ b/spec/unit/indirector/resource/ral_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe "Puppet::Resource::Ral" do - describe "find" do + describe "find", :fails_on_windows => true do before do @request = stub 'request', :key => "user/root" end diff --git a/spec/unit/indirector/resource_type/parser_spec.rb b/spec/unit/indirector/resource_type/parser_spec.rb index c4fc455a0..67ea73fd6 100755 --- a/spec/unit/indirector/resource_type/parser_spec.rb +++ b/spec/unit/indirector/resource_type/parser_spec.rb @@ -25,7 +25,7 @@ describe Puppet::Indirector::ResourceType::Parser do @terminus.find(@request).should == type end - it "should attempt to load the type if none is found in memory" do + it "should attempt to load the type if none is found in memory", :fails_on_windows => true do dir = tmpdir("find_a_type") FileUtils.mkdir_p(dir) Puppet[:modulepath] = dir @@ -122,13 +122,13 @@ describe Puppet::Indirector::ResourceType::Parser do @terminus.search(@request).should be_nil end - it "should load all resource types from all search paths" do + it "should load all resource types from all search paths", :fails_on_windows => true do dir = tmpdir("searching_in_all") first = File.join(dir, "first") second = File.join(dir, "second") FileUtils.mkdir_p(first) FileUtils.mkdir_p(second) - Puppet[:modulepath] = "#{first}:#{second}" + Puppet[:modulepath] = "#{first}#{File::PATH_SEPARATOR}#{second}" # Make a new request, since we've reset the env @request = Puppet::Indirector::Request.new(:resource_type, :search, "*") diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb index 5637080e8..042b7ca16 100755 --- a/spec/unit/indirector/rest_spec.rb +++ b/spec/unit/indirector/rest_spec.rb @@ -90,6 +90,54 @@ describe Puppet::Indirector::REST do @rest_class.port.should == 543 end + describe "when making http requests" do + it "should provide a suggestive error message when certificate verify failed" do + connection = Net::HTTP.new('my_server', 8140) + @searcher.stubs(:network).returns(connection) + + connection.stubs(:get).raises(OpenSSL::SSL::SSLError.new('certificate verify failed')) + + expect do + @searcher.http_request(:get, stub('request')) + end.to raise_error(/This is often because the time is out of sync on the server or client/) + end + + it "should provide a helpful error message when hostname was not match with server certificate" do + Puppet[:certdnsnames] = 'foo:bar:baz' + csr = OpenSSL::X509::Request.new + csr.subject = OpenSSL::X509::Name.new([['CN', 'not_my_server']]) + csr.public_key = OpenSSL::PKey::RSA.generate(Puppet[:keylength]).public_key + cert = Puppet::SSL::CertificateFactory.new('server', csr, csr, 14).result + + connection = Net::HTTP.new('my_server', 8140) + @searcher.stubs(:network).returns(connection) + ssl_context = OpenSSL::SSL::SSLContext.new + ssl_context.stubs(:current_cert).returns(cert) + connection.stubs(:get).with do + connection.verify_callback.call(true, ssl_context) + end.raises(OpenSSL::SSL::SSLError.new('hostname was not match with server certificate')) + + msg = /Server hostname 'my_server' did not match server certificate; expected one of (.+)/ + expect { @searcher.http_request(:get, stub('request')) }.to( + raise_error(Puppet::Error, msg) do |error| + error.message =~ msg + $1.split(', ').should =~ ['foo', 'bar', 'baz', 'not_my_server'] + end + ) + end + + it "should pass along the error message otherwise" do + connection = Net::HTTP.new('my_server', 8140) + @searcher.stubs(:network).returns(connection) + + connection.stubs(:get).raises(OpenSSL::SSL::SSLError.new('some other message')) + + expect do + @searcher.http_request(:get, stub('request')) + end.to raise_error(/some other message/) + end + end + describe "when deserializing responses" do it "should return nil if the response code is 404" do response = mock 'response' @@ -219,7 +267,7 @@ describe Puppet::Indirector::REST do describe "when doing a find" do before :each do - @connection = stub('mock http connection', :get => @response) + @connection = stub('mock http connection', :get => @response, :verify_callback= => nil) @searcher.stubs(:network).returns(@connection) # neuter the network connection # Use a key with spaces, so we can test escaping @@ -313,7 +361,7 @@ describe Puppet::Indirector::REST do describe "when doing a head" do before :each do - @connection = stub('mock http connection', :head => @response) + @connection = stub('mock http connection', :head => @response, :verify_callback= => nil) @searcher.stubs(:network).returns(@connection) # Use a key with spaces, so we can test escaping @@ -349,7 +397,7 @@ describe Puppet::Indirector::REST do describe "when doing a search" do before :each do - @connection = stub('mock http connection', :get => @response) + @connection = stub('mock http connection', :get => @response, :verify_callback= => nil) @searcher.stubs(:network).returns(@connection) # neuter the network connection @model.stubs(:convert_from_multiple) @@ -397,7 +445,7 @@ describe Puppet::Indirector::REST do describe "when doing a destroy" do before :each do - @connection = stub('mock http connection', :delete => @response) + @connection = stub('mock http connection', :delete => @response, :verify_callback= => nil) @searcher.stubs(:network).returns(@connection) # neuter the network connection @request = Puppet::Indirector::Request.new(:foo, :destroy, "foo bar") @@ -453,7 +501,7 @@ describe Puppet::Indirector::REST do describe "when doing a save" do before :each do - @connection = stub('mock http connection', :put => @response) + @connection = stub('mock http connection', :put => @response, :verify_callback= => nil) @searcher.stubs(:network).returns(@connection) # neuter the network connection @instance = stub 'instance', :render => "mydata", :mime => "mime" diff --git a/spec/unit/indirector/ssl_file_spec.rb b/spec/unit/indirector/ssl_file_spec.rb index 5d0859598..1a837f646 100755 --- a/spec/unit/indirector/ssl_file_spec.rb +++ b/spec/unit/indirector/ssl_file_spec.rb @@ -8,6 +8,8 @@ require 'spec_helper' require 'puppet/indirector/ssl_file' describe Puppet::Indirector::SslFile do + include PuppetSpec::Files + before :all do @indirection = stub 'indirection', :name => :testing, :model => @model Puppet::Indirector::Indirection.expects(:instance).with(:testing).returns(@indirection) @@ -21,7 +23,7 @@ describe Puppet::Indirector::SslFile do @setting = :certdir @file_class.store_in @setting - @path = "/tmp/my_directory" + @path = make_absolute("/tmp/my_directory") Puppet[:noop] = false Puppet[@setting] = @path Puppet[:trace] = false diff --git a/spec/unit/interface/action_spec.rb b/spec/unit/interface/action_spec.rb index cf8d61d51..c3f08e817 100755 --- a/spec/unit/interface/action_spec.rb +++ b/spec/unit/interface/action_spec.rb @@ -121,6 +121,7 @@ describe Puppet::Interface::Action do let :face do Puppet::Interface.new(:ruby_api, '1.0.0') do action :bar do + option "--bar" when_invoked do |*args| args.last end @@ -138,8 +139,8 @@ describe Puppet::Interface::Action do options.should == { :bar => "beer" } end - it "should call #validate_args on the action when invoked" do - face.get_action(:bar).expects(:validate_args).with([1, :two, 'three', {}]) + it "should call #validate_and_clean on the action when invoked" do + face.get_action(:bar).expects(:validate_and_clean).with({}).returns({}) face.bar 1, :two, 'three' end end @@ -171,6 +172,30 @@ describe Puppet::Interface::Action do face.get_action(:foo).options.should =~ [:bar] end + describe "option aliases" do + let :option do action.get_option :bar end + let :action do face.get_action :foo end + let :face do + Puppet::Interface.new(:action_level_options, '0.0.1') do + action :foo do + when_invoked do |options| options end + option "--bar", "--foo", "-b" + end + end + end + + it "should only list options and not aliases" do + action.options.should =~ [:bar] + end + + it "should use the canonical option name when passed aliases" do + name = option.name + option.aliases.each do |input| + face.foo(input => 1).should == { name => 1 } + end + end + end + describe "with both face and action options" do let :face do Puppet::Interface.new(:action_level_options, '0.0.1') do @@ -426,12 +451,12 @@ describe Puppet::Interface::Action do end it "should be invoked when calling a child action" do - subject.on_child(:foo => true, :bar => true).should == :on_child + subject.on_child(:foo => true).should == :on_child subject.reported.should == [ :child_before ] end it "should be invoked when calling a parent action" do - subject.on_parent(:foo => true, :bar => true).should == :on_parent + subject.on_parent(:foo => true).should == :on_parent subject.reported.should == [ :child_before ] end end @@ -443,12 +468,12 @@ describe Puppet::Interface::Action do end it "should be invoked when calling a child action" do - subject.on_child(:foo => true, :bar => true).should == :on_child + subject.on_child(:foo => true).should == :on_child subject.reported.should == [ :parent_before ] end it "should be invoked when calling a parent action" do - subject.on_parent(:foo => true, :bar => true).should == :on_parent + subject.on_parent(:foo => true).should == :on_parent subject.reported.should == [ :parent_before ] end end @@ -524,7 +549,7 @@ describe Puppet::Interface::Action do it "should return the block if asked" end - context "#validate_args" do + context "#validate_and_clean" do subject do Puppet::Interface.new(:validate_args, '1.0.0') do script :test do |options| true end @@ -541,5 +566,78 @@ describe Puppet::Interface::Action do expect { subject.test :foo => true, :f => true }. to raise_error ArgumentError, /Multiple aliases for the same option/ end + + it "should fail if an unknown option is passed" do + expect { subject.test :unknown => true }. + to raise_error ArgumentError, /Unknown options passed: unknown/ + end + + it "should report all the unknown options passed" do + expect { subject.test :unknown => true, :unseen => false }. + to raise_error ArgumentError, /Unknown options passed: unknown, unseen/ + end + end + + context "default option values" do + subject do + Puppet::Interface.new(:default_option_values, '1.0.0') do + action :foo do + option "--foo" do end + option "--bar" do end + when_invoked do |options| options end + end + end + end + + let :action do subject.get_action :foo end + let :option do action.get_option :foo end + + it "should not add options without defaults" do + subject.foo.should == {} + end + + it "should not add options without defaults, if options are given" do + subject.foo(:bar => 1).should == { :bar => 1 } + end + + it "should add the option default value when set" do + option.default = proc { 12 } + subject.foo.should == { :foo => 12 } + end + + it "should add the option default value when set, if other options are given" do + option.default = proc { 12 } + subject.foo(:bar => 1).should == { :foo => 12, :bar => 1 } + end + + it "should invoke the same default proc every time called" do + option.default = proc { @foo ||= {} } + subject.foo[:foo].object_id.should == subject.foo[:foo].object_id + end + + [nil, 0, 1, true, false, {}, []].each do |input| + it "should not override a passed option (#{input.inspect})" do + option.default = proc { :fail } + subject.foo(:foo => input).should == { :foo => input } + end + end + end + + context "runtime manipulations" do + subject do + Puppet::Interface.new(:runtime_manipulations, '1.0.0') do + action :foo do + when_invoked do |options| options end + end + end + end + + let :action do subject.get_action :foo end + + it "should be the face default action if default is set true" do + subject.get_default_action.should be_nil + action.default = true + subject.get_default_action.should == action + end end end diff --git a/spec/unit/interface/face_collection_spec.rb b/spec/unit/interface/face_collection_spec.rb index 4ad8787c5..514a624b1 100755 --- a/spec/unit/interface/face_collection_spec.rb +++ b/spec/unit/interface/face_collection_spec.rb @@ -25,39 +25,9 @@ describe Puppet::Interface::FaceCollection do @original_required.each {|f| $".push f unless $".include? f } end - describe "::prefix_match?" do - # want have - { ['1.0.0', '1.0.0'] => true, - ['1.0', '1.0.0'] => true, - ['1', '1.0.0'] => true, - ['1.0.0', '1.1.0'] => false, - ['1.0', '1.1.0'] => false, - ['1', '1.1.0'] => true, - ['1.0.1', '1.0.0'] => false, - }.each do |data, result| - it "should return #{result.inspect} for prefix_match?(#{data.join(', ')})" do - subject.prefix_match?(*data).should == result - end - end - end - - describe "::validate_version" do - { '10.10.10' => true, - '1.2.3.4' => false, - '10.10.10beta' => true, - '10.10' => false, - '123' => false, - 'v1.1.1' => false, - }.each do |input, result| - it "should#{result ? '' : ' not'} permit #{input.inspect}" do - subject.validate_version(input).should(result ? be_true : be_false) - end - end - end - describe "::[]" do before :each do - subject.instance_variable_get("@faces")[:foo]['0.0.1'] = 10 + subject.instance_variable_get("@faces")[:foo][SemVer.new('0.0.1')] = 10 end it "should return the face with the given name" do @@ -65,7 +35,8 @@ describe Puppet::Interface::FaceCollection do end it "should attempt to load the face if it isn't found" do - subject.expects(:require).with('puppet/face/bar') + subject.expects(:require).once.with('puppet/face/bar') + subject.expects(:require).once.with('puppet/face/0.0.1/bar') subject["bar", '0.0.1'] end @@ -75,13 +46,13 @@ describe Puppet::Interface::FaceCollection do end it "should return true if the face specified is registered" do - subject.instance_variable_get("@faces")[:foo]['0.0.1'] = 10 + subject.instance_variable_get("@faces")[:foo][SemVer.new('0.0.1')] = 10 subject["foo", '0.0.1'].should == 10 end it "should attempt to require the face if it is not registered" do subject.expects(:require).with do |file| - subject.instance_variable_get("@faces")[:bar]['0.0.1'] = true + subject.instance_variable_get("@faces")[:bar][SemVer.new('0.0.1')] = true file == 'puppet/face/bar' end subject["bar", '0.0.1'].should be_true @@ -94,7 +65,8 @@ describe Puppet::Interface::FaceCollection do it "should return false if the face file itself is missing" do subject.stubs(:require). - raises(LoadError, 'no such file to load -- puppet/face/bar') + raises(LoadError, 'no such file to load -- puppet/face/bar').then. + raises(LoadError, 'no such file to load -- puppet/face/0.0.1/bar') subject["bar", '0.0.1'].should be_false end @@ -127,11 +99,49 @@ describe Puppet::Interface::FaceCollection do end end + describe "::get_action_for_face" do + it "should return an action on the current face" do + Puppet::Face::FaceCollection.get_action_for_face(:huzzah, :bar, :current). + should be_an_instance_of Puppet::Interface::Action + end + + it "should return an action on an older version of a face" do + action = Puppet::Face::FaceCollection. + get_action_for_face(:huzzah, :obsolete, :current) + + action.should be_an_instance_of Puppet::Interface::Action + action.face.version.should == SemVer.new('1.0.0') + end + + it "should load the full older version of a face" do + action = Puppet::Face::FaceCollection. + get_action_for_face(:huzzah, :obsolete, :current) + + action.face.version.should == SemVer.new('1.0.0') + action.face.should be_action :obsolete_in_core + end + + it "should not add obsolete actions to the current version" do + action = Puppet::Face::FaceCollection. + get_action_for_face(:huzzah, :obsolete, :current) + + action.face.version.should == SemVer.new('1.0.0') + action.face.should be_action :obsolete_in_core + + current = Puppet::Face[:huzzah, :current] + current.version.should == SemVer.new('2.0.1') + current.should_not be_action :obsolete_in_core + current.should_not be_action :obsolete + end + end + describe "::register" do it "should store the face by name" do face = Puppet::Face.new(:my_face, '0.0.1') subject.register(face) - subject.instance_variable_get("@faces").should == {:my_face => {'0.0.1' => face}} + subject.instance_variable_get("@faces").should == { + :my_face => { face.version => face } + } end end diff --git a/spec/unit/interface/option_spec.rb b/spec/unit/interface/option_spec.rb index e77b46e79..e73561fba 100755 --- a/spec/unit/interface/option_spec.rb +++ b/spec/unit/interface/option_spec.rb @@ -97,4 +97,48 @@ describe Puppet::Interface::Option do end end end + + context "defaults" do + subject { Puppet::Interface::Option.new(face, "--foo") } + + it "should work sanely if member variables are used for state" do + subject.default = proc { @foo ||= 0; @foo += 1 } + subject.default.should == 1 + subject.default.should == 2 + subject.default.should == 3 + end + + context "with no default" do + it { should_not be_has_default } + its :default do should be_nil end + + it "should set a proc as default" do + expect { subject.default = proc { 12 } }.should_not raise_error + end + + [1, {}, [], Object.new, "foo"].each do |input| + it "should reject anything but a proc (#{input.class})" do + expect { subject.default = input }.to raise_error ArgumentError, /not a proc/ + end + end + end + + context "with a default" do + before :each do subject.default = proc { [:foo] } end + + it { should be_has_default } + its :default do should == [:foo] end + + it "should invoke the block every time" do + subject.default.object_id.should_not == subject.default.object_id + subject.default.should == subject.default + end + + it "should allow replacing the default proc" do + subject.default.should == [:foo] + subject.default = proc { :bar } + subject.default.should == :bar + end + end + end end diff --git a/spec/unit/interface_spec.rb b/spec/unit/interface_spec.rb index 8bbbcc857..4ff71ac3d 100755 --- a/spec/unit/interface_spec.rb +++ b/spec/unit/interface_spec.rb @@ -126,14 +126,11 @@ describe Puppet::Interface do end it "should try to require faces that are not known" do - pending "mocking require causes random stack overflow" - subject::FaceCollection.expects(:require).with "puppet/face/foo" - subject[:foo, '0.0.1'] + subject::FaceCollection.expects(:load_face).with(:foo, :current) + subject::FaceCollection.expects(:load_face).with(:foo, '0.0.1') + expect { subject[:foo, '0.0.1'] }.to raise_error Puppet::Error end - it "should be able to load all actions in all search paths" - - it_should_behave_like "things that declare options" do def add_options_to(&block) subject.new(:with_options, '0.0.1', &block) @@ -174,6 +171,14 @@ describe Puppet::Interface do face.get_action(:foo).options.should =~ [:quux] face.get_action(:bar).options.should =~ [:quux] end + + it "should only list options and not aliases" do + face = subject.new(:face_options, '0.0.1') do + option "--bar", "-b", "--foo-bar" + end + face.options.should =~ [:bar] + end + end describe "with inherited options" do diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb index 8d38657f9..a0f64c6d3 100755 --- a/spec/unit/module_spec.rb +++ b/spec/unit/module_spec.rb @@ -275,7 +275,7 @@ describe Puppet::Module do FileUtils.mkdir_p(first) FileUtils.mkdir_p(second) - Puppet[:modulepath] = "#{first}:#{second}" + Puppet[:modulepath] = "#{first}#{File::PATH_SEPARATOR}#{second}" modpath = File.join(first, "foo") FileUtils.mkdir_p(modpath) @@ -294,7 +294,7 @@ describe Puppet::Module do FileUtils.mkdir_p(first) FileUtils.mkdir_p(second) - Puppet[:modulepath] = "#{first}:#{second}" + Puppet[:modulepath] = "#{first}#{File::PATH_SEPARATOR}#{second}" modpath = File.join(second, "foo") FileUtils.mkdir_p(modpath) @@ -505,12 +505,38 @@ describe Puppet::Module do mod.metadata_file.should == mod.metadata_file end - it "should know if it has a metadata file" do + it "should have metadata if it has a metadata file and its data is not empty" do FileTest.expects(:exist?).with(@module.metadata_file).returns true + File.stubs(:read).with(@module.metadata_file).returns "{\"foo\" : \"bar\"}" @module.should be_has_metadata end + it "should have metadata if it has a metadata file and its data is not empty" do + FileTest.expects(:exist?).with(@module.metadata_file).returns true + File.stubs(:read).with(@module.metadata_file).returns "{\"foo\" : \"bar\"}" + + @module.should be_has_metadata + end + + it "should not have metadata if has a metadata file and its data is empty" do + FileTest.expects(:exist?).with(@module.metadata_file).returns true + File.stubs(:read).with(@module.metadata_file).returns "/* ++-----------------------------------------------------------------------+ +| | +| ==> DO NOT EDIT THIS FILE! <== | +| | +| You should edit the `Modulefile` and run `puppet-module build` | +| to generate the `metadata.json` file for your releases. | +| | ++-----------------------------------------------------------------------+ +*/ + +{}" + + @module.should_not be_has_metadata + end + it "should know if it is missing a metadata file" do FileTest.expects(:exist?).with(@module.metadata_file).returns false @@ -528,16 +554,16 @@ describe Puppet::Module do Puppet::Module.new("yay") end - describe "when loading the medatada file", :if => Puppet.features.json? do + describe "when loading the medatada file", :if => Puppet.features.pson? do before do @data = { - :license => "GPL2", - :author => "luke", - :version => "1.0", - :source => "http://foo/", + :license => "GPL2", + :author => "luke", + :version => "1.0", + :source => "http://foo/", :puppetversion => "0.25" } - @text = @data.to_json + @text = @data.to_pson @module = Puppet::Module.new("foo") @module.stubs(:metadata_file).returns "/my/file" @@ -552,9 +578,12 @@ describe Puppet::Module do it "should fail if #{attr} is not present in the metadata file" do @data.delete(attr.to_sym) - @text = @data.to_json + @text = @data.to_pson File.stubs(:read).with("/my/file").returns @text - lambda { @module.load_metadata }.should raise_error(Puppet::Module::MissingMetadata) + lambda { @module.load_metadata }.should raise_error( + Puppet::Module::MissingMetadata, + "No #{attr} module metadata provided for foo" + ) end end diff --git a/spec/unit/network/authconfig_spec.rb b/spec/unit/network/authconfig_spec.rb index c47b2e0c5..ca94cc1ab 100755 --- a/spec/unit/network/authconfig_spec.rb +++ b/spec/unit/network/authconfig_spec.rb @@ -184,6 +184,29 @@ describe Puppet::Network::AuthConfig do @authconfig.read end + it "should strip whitespace around ACE" do + acl = stub 'acl', :info + + @fd.stubs(:each).multiple_yields('[puppetca]', ' allow 127.0.0.1 , 172.16.10.0 ') + @rights.stubs(:newright).with("[puppetca]", 1, 'dummy').returns(acl) + + acl.expects(:allow).with('127.0.0.1') + acl.expects(:allow).with('172.16.10.0') + + @authconfig.read + end + + it "should allow ACE inline comments" do + acl = stub 'acl', :info + + @fd.stubs(:each).multiple_yields('[puppetca]', ' allow 127.0.0.1 # will it work?') + @rights.stubs(:newright).with("[puppetca]", 1, 'dummy').returns(acl) + + acl.expects(:allow).with('127.0.0.1') + + @authconfig.read + end + it "should create an allow ACE on each subsequent allow" do acl = stub 'acl', :info diff --git a/spec/unit/network/client_spec.rb b/spec/unit/network/client_spec.rb deleted file mode 100755 index 102a053c0..000000000 --- a/spec/unit/network/client_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env rspec -# -# Created by Luke Kanies on 2008-3-24. -# Copyright (c) 2008. All rights reserved. - -require 'spec_helper' - -require 'puppet/network/client' - -describe Puppet::Network::Client do - before do - Puppet.settings.stubs(:use).returns(true) - Puppet::Network::HttpPool.stubs(:cert_setup) - end - - describe "when keep-alive is enabled" do - before do - Puppet::Network::HttpPool.stubs(:keep_alive?).returns true - end - it "should start the http client up on creation" do - http = mock 'http' - http.stub_everything - http.expects(:start) - Net::HTTP.stubs(:new).returns http - - # Pick a random subclass... - Puppet::Network::Client.runner.new :Server => Puppet[:server] - end - end - - describe "when keep-alive is disabled" do - before do - Puppet::Network::HttpPool.stubs(:keep_alive?).returns false - end - it "should not start the http client up on creation" do - http = mock 'http' - http.stub_everything - http.expects(:start).never - Net::HTTP.stubs(:new).returns http - - # Pick a random subclass... - Puppet::Network::Client.runner.new :Server => Puppet[:server] - end - end -end diff --git a/spec/unit/network/handler/fileserver_spec.rb b/spec/unit/network/handler/fileserver_spec.rb index 08852634d..93f124882 100755 --- a/spec/unit/network/handler/fileserver_spec.rb +++ b/spec/unit/network/handler/fileserver_spec.rb @@ -41,12 +41,12 @@ describe Puppet::Network::Handler::FileServer do @mount.list("/no_such_file", false, false).should be(nil) end - it "should list a symbolic link as a file when given the link path" do + it "should list a symbolic link as a file when given the link path", :unless => Puppet.features.microsoft_windows? do File.symlink(@file, @link) @mount.list("/aLink", false, false).should == [["/", "file"]] end - it "should return nil for a dangling symbolic link when given the link path" do + it "should return nil for a dangling symbolic link when given the link path", :unless => Puppet.features.microsoft_windows? do File.symlink("/some/where", @link) @mount.list("/aLink", false, false).should be(nil) end @@ -106,18 +106,18 @@ describe Puppet::Network::Handler::FileServer do list.sort.should == [ ["/aFile", "file"], ["/", "directory"] , ["/nested_dir", "directory"], ["/nested_dir/nested_dir_file", "file"]].sort end - it "should list a valid symbolic link as a file when recursing base dir" do + it "should list a valid symbolic link as a file when recursing base dir", :unless => Puppet.features.microsoft_windows? do File.symlink(@file, @link) list = @mount.list("/", true, false) list.sort.should == [ ["/", "directory"], ["/aFile", "file"], ["/aLink", "file"] ].sort end - it "should not error when a dangling symlink is present" do + it "should not error when a dangling symlink is present", :unless => Puppet.features.microsoft_windows? do File.symlink("/some/where", @link) lambda { @mount.list("/", true, false) }.should_not raise_error end - it "should return the directory contents of valid entries when a dangling symlink is present" do + it "should return the directory contents of valid entries when a dangling symlink is present", :unless => Puppet.features.microsoft_windows? do File.symlink("/some/where", @link) list = @mount.list("/", true, false) list.sort.should == [ ["/aFile", "file"], ["/", "directory"] ].sort diff --git a/spec/unit/network/http/webrick_spec.rb b/spec/unit/network/http/webrick_spec.rb index be74a1052..8504b02e3 100755 --- a/spec/unit/network/http/webrick_spec.rb +++ b/spec/unit/network/http/webrick_spec.rb @@ -8,13 +8,13 @@ require 'puppet/network/handler' require 'puppet/network/http' require 'puppet/network/http/webrick' -describe Puppet::Network::HTTP::WEBrick, "after initializing" do +describe Puppet::Network::HTTP::WEBrick, "after initializing", :unless => Puppet.features.microsoft_windows? do it "should not be listening" do Puppet::Network::HTTP::WEBrick.new.should_not be_listening end end -describe Puppet::Network::HTTP::WEBrick, "when turning on listening" do +describe Puppet::Network::HTTP::WEBrick, "when turning on listening", :unless => Puppet.features.microsoft_windows? do before do @mock_webrick = stub('webrick', :[] => {}, :listeners => [], :status => :Running) [:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)} @@ -143,7 +143,7 @@ describe Puppet::Network::HTTP::WEBrick, "when turning on listening" do end -describe Puppet::Network::HTTP::WEBrick, "when looking up the class to handle a protocol" do +describe Puppet::Network::HTTP::WEBrick, "when looking up the class to handle a protocol", :unless => Puppet.features.microsoft_windows? do it "should require a protocol" do lambda { Puppet::Network::HTTP::WEBrick.class_for_protocol }.should raise_error(ArgumentError) end @@ -161,7 +161,7 @@ describe Puppet::Network::HTTP::WEBrick, "when looking up the class to handle a end end -describe Puppet::Network::HTTP::WEBrick, "when turning off listening" do +describe Puppet::Network::HTTP::WEBrick, "when turning off listening", :unless => Puppet.features.microsoft_windows? do before do @mock_webrick = stub('webrick', :[] => {}, :listeners => [], :status => :Running) [:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)} @@ -188,7 +188,7 @@ describe Puppet::Network::HTTP::WEBrick, "when turning off listening" do end end -describe Puppet::Network::HTTP::WEBrick do +describe Puppet::Network::HTTP::WEBrick, :unless => Puppet.features.microsoft_windows? do before do @mock_webrick = stub('webrick', :[] => {}) [:mount, :start, :shutdown].each {|meth| @mock_webrick.stubs(meth)} diff --git a/spec/unit/network/http_pool_spec.rb b/spec/unit/network/http_pool_spec.rb index c5d3e0470..1961f3029 100755 --- a/spec/unit/network/http_pool_spec.rb +++ b/spec/unit/network/http_pool_spec.rb @@ -8,15 +8,9 @@ require 'puppet/network/http_pool' describe Puppet::Network::HttpPool do after do - Puppet::Util::Cacher.expire - Puppet::Network::HttpPool.clear_http_instances Puppet::Network::HttpPool.instance_variable_set("@ssl_host", nil) end - it "should have keep-alive disabled" do - Puppet::Network::HttpPool::HTTP_KEEP_ALIVE.should be_false - end - it "should use the global SSL::Host instance to get its certificate information" do host = mock 'host' Puppet::SSL::Host.expects(:localhost).with.returns host @@ -58,71 +52,10 @@ describe Puppet::Network::HttpPool do Puppet::Network::HttpPool.http_instance("me", 54321).open_timeout.should == 120 end - describe "and http keep-alive is enabled" do - before do - Puppet::Network::HttpPool.stubs(:keep_alive?).returns true - end - - it "should cache http instances" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - old = Puppet::Network::HttpPool.http_instance("me", 54321) - Puppet::Network::HttpPool.http_instance("me", 54321).should equal(old) - end - - it "should have a mechanism for getting a new http instance instead of the cached instance" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - old = Puppet::Network::HttpPool.http_instance("me", 54321) - Puppet::Network::HttpPool.http_instance("me", 54321, true).should_not equal(old) - end - - it "should close existing, open connections when requesting a new connection" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - old = Puppet::Network::HttpPool.http_instance("me", 54321) - old.expects(:started?).returns(true) - old.expects(:finish) - Puppet::Network::HttpPool.http_instance("me", 54321, true) - end - - it "should have a mechanism for clearing the http cache" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - old = Puppet::Network::HttpPool.http_instance("me", 54321) - Puppet::Network::HttpPool.http_instance("me", 54321).should equal(old) - old = Puppet::Network::HttpPool.http_instance("me", 54321) - Puppet::Network::HttpPool.clear_http_instances - Puppet::Network::HttpPool.http_instance("me", 54321).should_not equal(old) - end - - it "should close open http connections when clearing the cache" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - one = Puppet::Network::HttpPool.http_instance("me", 54321) - one.expects(:started?).returns(true) - one.expects(:finish).returns(true) - Puppet::Network::HttpPool.clear_http_instances - end - - it "should not close unopened http connections when clearing the cache" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - one = Puppet::Network::HttpPool.http_instance("me", 54321) - one.expects(:started?).returns(false) - one.expects(:finish).never - Puppet::Network::HttpPool.clear_http_instances - end - end - - describe "and http keep-alive is disabled" do - before do - Puppet::Network::HttpPool.stubs(:keep_alive?).returns false - end - - it "should not cache http instances" do - stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 - old = Puppet::Network::HttpPool.http_instance("me", 54321) - Puppet::Network::HttpPool.http_instance("me", 54321).should_not equal(old) - end - end - - after do - Puppet::Network::HttpPool.clear_http_instances + it "should not cache http instances" do + stub_settings :http_proxy_host => "myhost", :http_proxy_port => 432, :configtimeout => 120 + old = Puppet::Network::HttpPool.http_instance("me", 54321) + Puppet::Network::HttpPool.http_instance("me", 54321).should_not equal(old) end end diff --git a/spec/unit/network/rest_authconfig_spec.rb b/spec/unit/network/rest_authconfig_spec.rb index e1403997f..bebbb874f 100755 --- a/spec/unit/network/rest_authconfig_spec.rb +++ b/spec/unit/network/rest_authconfig_spec.rb @@ -29,7 +29,7 @@ describe Puppet::Network::RestAuthConfig do params = {:ip => "127.0.0.1", :node => "me", :environment => :env, :authenticated => true} @acl.expects(:is_request_forbidden_and_why?).with("path", :save, "to/resource", params).returns(nil) - @authconfig.allowed?("path", :save, "to/resource", params) + @authconfig.check_authorization("path", :save, "to/resource", params) end describe "when defining an acl with mk_acl" do diff --git a/spec/unit/node/environment_spec.rb b/spec/unit/node/environment_spec.rb index d1badfa3a..78d383440 100755 --- a/spec/unit/node/environment_spec.rb +++ b/spec/unit/node/environment_spec.rb @@ -1,6 +1,8 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'tmpdir' + require 'puppet/node/environment' require 'puppet/util/execution' @@ -10,10 +12,6 @@ describe Puppet::Node::Environment do Puppet::Node::Environment.clear end - it "should include the Cacher module" do - Puppet::Node::Environment.ancestors.should be_include(Puppet::Util::Cacher) - end - it "should use the filetimeout for the ttl for the modulepath" do Puppet::Node::Environment.attr_ttl(:modulepath).should == Integer(Puppet[:filetimeout]) end @@ -22,10 +20,6 @@ describe Puppet::Node::Environment do Puppet::Node::Environment.attr_ttl(:modules).should == Integer(Puppet[:filetimeout]) end - it "should use the filetimeout for the ttl for the manifestdir" do - Puppet::Node::Environment.attr_ttl(:manifestdir).should == Integer(Puppet[:filetimeout]) - end - it "should use the default environment if no name is provided while initializing an environment" do Puppet.settings.expects(:value).with(:environment).returns("one") Puppet::Node::Environment.new.name.should == :one @@ -109,27 +103,15 @@ describe Puppet::Node::Environment do end end - [:modulepath, :manifestdir].each do |setting| - it "should validate the #{setting} directories" do - path = %w{/one /two}.join(File::PATH_SEPARATOR) - - env = Puppet::Node::Environment.new("testing") - env.stubs(:[]).with(setting).returns path - - env.expects(:validate_dirs).with(%w{/one /two}) - - env.send(setting) - end + it "should validate the modulepath directories" do + real_file = tmpdir('moduledir') + path = %W[/one /two #{real_file}].join(File::PATH_SEPARATOR) - it "should return the validated dirs for #{setting}" do - path = %w{/one /two}.join(File::PATH_SEPARATOR) + Puppet[:modulepath] = path - env = Puppet::Node::Environment.new("testing") - env.stubs(:[]).with(setting).returns path - env.stubs(:validate_dirs).returns %w{/one /two} + env = Puppet::Node::Environment.new("testing") - env.send(setting).should == %w{/one /two} - end + env.modulepath.should == [real_file] end it "should prefix the value of the 'PUPPETLIB' environment variable to the module path if present" do @@ -144,21 +126,26 @@ describe Puppet::Node::Environment do end describe "when validating modulepath or manifestdir directories" do + before :each do + @path_one = make_absolute('/one') + @path_two = make_absolute('/two') + end + it "should not return non-directories" do env = Puppet::Node::Environment.new("testing") - FileTest.expects(:directory?).with("/one").returns true - FileTest.expects(:directory?).with("/two").returns false + FileTest.expects(:directory?).with(@path_one).returns true + FileTest.expects(:directory?).with(@path_two).returns false - env.validate_dirs(%w{/one /two}).should == %w{/one} + env.validate_dirs([@path_one, @path_two]).should == [@path_one] end it "should use the current working directory to fully-qualify unqualified paths" do FileTest.stubs(:directory?).returns true env = Puppet::Node::Environment.new("testing") - two = File.join(Dir.getwd, "two") - env.validate_dirs(%w{/one two}).should == ["/one", two] + two = File.expand_path(File.join(Dir.getwd, "two")) + env.validate_dirs([@path_one, 'two']).should == [@path_one, two] end end diff --git a/spec/unit/node/facts_spec.rb b/spec/unit/node/facts_spec.rb index efaa76e12..b3a0f92dd 100755 --- a/spec/unit/node/facts_spec.rb +++ b/spec/unit/node/facts_spec.rb @@ -68,10 +68,6 @@ describe Puppet::Node::Facts, "when indirecting" do before do @indirection = stub 'indirection', :request => mock('request'), :name => :facts - # We have to clear the cache so that the facts ask for our indirection stub, - # instead of anything that might be cached. - Puppet::Util::Cacher.expire - @facts = Puppet::Node::Facts.new("me", "one" => "two") end @@ -128,6 +124,20 @@ describe Puppet::Node::Facts, "when indirecting" do result['timestamp'].should == facts.timestamp.to_s result['expiration'].should == facts.expiration.to_s end + + it "should not include nil values" do + facts = Puppet::Node::Facts.new("foo", {'a' => 1, 'b' => 2, 'c' => 3}) + pson = PSON.parse(facts.to_pson) + pson.should_not be_include("expiration") + end + + it "should be able to handle nil values" do + pson = %Q({"name": "foo", "values": {"a": "1", "b": "2", "c": "3"}}) + format = Puppet::Network::FormatHandler.format('pson') + facts = format.intern(Puppet::Node::Facts,pson) + facts.name.should == 'foo' + facts.expiration.should be_nil + end end end end diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb index c15093d90..5f3e3b44d 100755 --- a/spec/unit/node_spec.rb +++ b/spec/unit/node_spec.rb @@ -3,6 +3,10 @@ require 'spec_helper' require 'matchers/json' describe Puppet::Node do + it "should register its document type as Node" do + PSON.registered_document_types["Node"].should equal(Puppet::Node) + end + describe "when managing its environment" do it "should use any set environment" do Puppet::Node.new("foo", :environment => "bar").environment.name.should == :bar @@ -36,6 +40,73 @@ describe Puppet::Node do node.environment.name.should == :bar end end + + describe "when converting to json" do + before do + @node = Puppet::Node.new("mynode") + end + + it "should provide its name" do + @node.should set_json_attribute('name').to("mynode") + end + + it "should produce a hash with the document_type set to 'Node'" do + @node.should set_json_document_type_to("Node") + end + + it "should include the classes if set" do + @node.classes = %w{a b c} + @node.should set_json_attribute("classes").to(%w{a b c}) + end + + it "should not include the classes if there are none" do + @node.should_not set_json_attribute('classes') + end + + it "should include parameters if set" do + @node.parameters = {"a" => "b", "c" => "d"} + @node.should set_json_attribute('parameters').to({"a" => "b", "c" => "d"}) + end + + it "should not include the parameters if there are none" do + @node.should_not set_json_attribute('parameters') + end + + it "should include the environment" do + @node.environment = "production" + @node.should set_json_attribute('environment').to('production') + end + end + + describe "when converting from json" do + before do + @node = Puppet::Node.new("mynode") + @format = Puppet::Network::FormatHandler.format('pson') + end + + def from_json(json) + @format.intern(Puppet::Node, json) + end + + it "should set its name" do + Puppet::Node.should read_json_attribute('name').from(@node.to_pson).as("mynode") + end + + it "should include the classes if set" do + @node.classes = %w{a b c} + Puppet::Node.should read_json_attribute('classes').from(@node.to_pson).as(%w{a b c}) + end + + it "should include parameters if set" do + @node.parameters = {"a" => "b", "c" => "d"} + Puppet::Node.should read_json_attribute('parameters').from(@node.to_pson).as({"a" => "b", "c" => "d"}) + end + + it "should include the environment" do + @node.environment = "production" + Puppet::Node.should read_json_attribute('environment').from(@node.to_pson).as(Puppet::Node::Environment.new(:production)) + end + end end describe Puppet::Node, "when initializing" do @@ -136,10 +207,6 @@ describe Puppet::Node, "when indirecting" do it "should not have a cache class defined" do Puppet::Node.indirection.cache_class.should be_nil end - - after do - Puppet::Util::Cacher.expire - end end describe Puppet::Node, "when generating the list of names to search through" do diff --git a/spec/unit/other/selinux_spec.rb b/spec/unit/other/selinux_spec.rb index 216feaf1f..f20951868 100755 --- a/spec/unit/other/selinux_spec.rb +++ b/spec/unit/other/selinux_spec.rb @@ -5,11 +5,13 @@ require 'puppet/type/selboolean' require 'puppet/type/selmodule' describe Puppet::Type.type(:file), " when manipulating file contexts" do + include PuppetSpec::Files + before :each do @file = Puppet::Type::File.new( - :name => "/tmp/foo", + :name => make_absolute("/tmp/foo"), :ensure => "file", :seluser => "user_u", :selrole => "role_r", diff --git a/spec/unit/parameter_spec.rb b/spec/unit/parameter_spec.rb index 04556c013..1ed211957 100755 --- a/spec/unit/parameter_spec.rb +++ b/spec/unit/parameter_spec.rb @@ -25,16 +25,6 @@ describe Puppet::Parameter do @parameter.to_s.should == @parameter.name.to_s end - it "should be able to use cached attributes" do - Puppet::Parameter.ancestors.should be_include(Puppet::Util::Cacher) - end - - it "should use the resource catalog for expiration" do - catalog = mock 'catalog' - @resource.stubs(:catalog).returns catalog - @parameter.expirer.should equal(catalog) - end - [:line, :file, :version].each do |data| it "should return its resource's #{data} as its #{data}" do @resource.expects(data).returns "foo" diff --git a/spec/unit/parser/ast/casestatement_spec.rb b/spec/unit/parser/ast/casestatement_spec.rb index e21190706..a76a9ae1f 100755 --- a/spec/unit/parser/ast/casestatement_spec.rb +++ b/spec/unit/parser/ast/casestatement_spec.rb @@ -154,7 +154,7 @@ describe Puppet::Parser::AST::CaseStatement do tests.each do |should, values| values.each do |value| @scope = Puppet::Parser::Scope.new - @scope.setvar("testparam", value) + @scope['testparam'] = value result = ast.evaluate(@scope) result.should == should diff --git a/spec/unit/parser/ast/leaf_spec.rb b/spec/unit/parser/ast/leaf_spec.rb index ff3fed5e9..36c790a41 100755 --- a/spec/unit/parser/ast/leaf_spec.rb +++ b/spec/unit/parser/ast/leaf_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Puppet::Parser::AST::Leaf do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new @value = stub 'value' @leaf = Puppet::Parser::AST::Leaf.new(:value => @value) end @@ -56,7 +56,7 @@ end describe Puppet::Parser::AST::Concat do describe "when evaluating" do before :each do - @scope = stub_everything 'scope' + @scope = Puppet::Parser::Scope.new end it "should interpolate variables and concatenate their values" do one = Puppet::Parser::AST::String.new(:value => "one") @@ -86,7 +86,7 @@ end describe Puppet::Parser::AST::Undef do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new @undef = Puppet::Parser::AST::Undef.new(:value => :undef) end @@ -101,12 +101,12 @@ end describe Puppet::Parser::AST::HashOrArrayAccess do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new end describe "when evaluating" do it "should evaluate the variable part if necessary" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns(["b"]) + @scope["a"] = ["b"] variable = stub 'variable', :evaluate => "a" access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => variable, :key => 0 ) @@ -117,7 +117,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should evaluate the access key part if necessary" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns(["b"]) + @scope["a"] = ["b"] index = stub 'index', :evaluate => 0 access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => index ) @@ -128,7 +128,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should be able to return an array member" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns(["val1", "val2", "val3"]) + @scope["a"] = %w{val1 val2 val3} access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => 1 ) @@ -136,7 +136,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should be able to return an array member when index is a stringified number" do - @scope.stubs(:lookupvar).with { |name,options| name == "a" }.returns(["val1", "val2", "val3"]) + @scope["a"] = %w{val1 val2 val3} access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "1" ) @@ -144,7 +144,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should raise an error when accessing an array with a key" do - @scope.stubs(:lookupvar).with { |name,options| name == "a"}.returns(["val1", "val2", "val3"]) + @scope["a"] = ["val1", "val2", "val3"] access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" ) @@ -152,7 +152,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should be able to return an hash value" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns({ "key1" => "val1", "key2" => "val2", "key3" => "val3" }) + @scope["a"] = { "key1" => "val1", "key2" => "val2", "key3" => "val3" } access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key2" ) @@ -160,7 +160,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should be able to return an hash value with a numerical key" do - @scope.stubs(:lookupvar).with { |name,options| name == "a"}.returns({ "key1" => "val1", "key2" => "val2", "45" => "45", "key3" => "val3" }) + @scope["a"] = { "key1" => "val1", "key2" => "val2", "45" => "45", "key3" => "val3" } access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "45" ) @@ -168,7 +168,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should raise an error if the variable lookup didn't return an hash or an array" do - @scope.stubs(:lookupvar).with { |name,options| name == "a"}.returns("I'm a string") + @scope["a"] = "I'm a string" access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key2" ) @@ -176,8 +176,6 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should raise an error if the variable wasn't in the scope" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns(nil) - access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key2" ) lambda { access.evaluate(@scope) }.should raise_error @@ -189,7 +187,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should work with recursive hash access" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns({ "key" => { "subkey" => "b" }}) + @scope["a"] = { "key" => { "subkey" => "b" }} access1 = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key") access2 = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => access1, :key => "subkey") @@ -198,7 +196,7 @@ describe Puppet::Parser::AST::HashOrArrayAccess do end it "should work with interleaved array and hash access" do - @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns({ "key" => [ "a" , "b" ]}) + @scope['a'] = { "key" => [ "a" , "b" ]} access1 = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key") access2 = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => access1, :key => 1) @@ -210,16 +208,16 @@ describe Puppet::Parser::AST::HashOrArrayAccess do describe "when assigning" do it "should add a new key and value" do scope = Puppet::Parser::Scope.new - scope.setvar("a", { 'a' => 'b' }) + scope['a'] = { 'a' => 'b' } access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "b") access.assign(scope, "c" ) - scope.lookupvar("a").should be_include("b") + scope['a'].should be_include("b") end it "should raise an error when assigning an array element with a key" do - @scope.stubs(:lookupvar).with { |name,options| name == "a"}.returns([]) + @scope['a'] = [] access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "get_me_the_second_element_please" ) @@ -228,16 +226,16 @@ describe Puppet::Parser::AST::HashOrArrayAccess do it "should be able to return an array member when index is a stringified number" do scope = Puppet::Parser::Scope.new - scope.setvar("a", []) + scope['a'] = [] access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "0" ) access.assign(scope, "val2") - scope.lookupvar("a").should == ["val2"] + scope['a'].should == ["val2"] end it "should raise an error when trying to overwrite an hash value" do - @scope.stubs(:lookupvar).with { |name,options| name == "a" }.returns({ "key" => [ "a" , "b" ]}) + @scope['a'] = { "key" => [ "a" , "b" ]} access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key") lambda { access.assign(@scope, "test") }.should raise_error @@ -247,7 +245,7 @@ end describe Puppet::Parser::AST::Regex do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new end describe "when initializing" do @@ -330,22 +328,21 @@ end describe Puppet::Parser::AST::Variable do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new @var = Puppet::Parser::AST::Variable.new(:value => "myvar", :file => 'my.pp', :line => 222) end it "should lookup the variable in scope" do - @scope.expects(:lookupvar).with { |name,options| name == "myvar" }.returns(:myvalue) + @scope["myvar"] = :myvalue @var.safeevaluate(@scope).should == :myvalue end it "should pass the source location to lookupvar" do - @scope.expects(:lookupvar).with { |name,options| name == "myvar" and options[:file] == 'my.pp' and options[:line] == 222 }.returns(:myvalue) + @scope.setvar("myvar", :myvalue, :file => 'my.pp', :line => 222 ) @var.safeevaluate(@scope).should == :myvalue end it "should return undef if the variable wasn't set" do - @scope.expects(:lookupvar).with { |name,options| name == "myvar" }.returns(:undefined) @var.safeevaluate(@scope).should == :undef end @@ -359,7 +356,7 @@ end describe Puppet::Parser::AST::HostName do before :each do - @scope = stub 'scope' + @scope = Puppet::Parser::Scope.new @value = stub 'value', :=~ => false @value.stubs(:to_s).returns(@value) @value.stubs(:downcase).returns(@value) diff --git a/spec/unit/parser/ast/resource_reference_spec.rb b/spec/unit/parser/ast/resource_reference_spec.rb index 4d1c191cf..4e069cca0 100755 --- a/spec/unit/parser/ast/resource_reference_spec.rb +++ b/spec/unit/parser/ast/resource_reference_spec.rb @@ -36,7 +36,7 @@ describe Puppet::Parser::AST::ResourceReference do end it "should return an array of resources if given a variable containing an array of titles" do - @scope.setvar("my_files", ["foo", "bar"]) + @scope["my_files"] = ["foo", "bar"] titles = Puppet::Parser::AST::Variable.new(:value => "my_files") ref = newref('File', titles) ref.evaluate(@scope).should == [ diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb index fcce9f6f4..411d1b862 100755 --- a/spec/unit/parser/compiler_spec.rb +++ b/spec/unit/parser/compiler_spec.rb @@ -43,6 +43,8 @@ class CompilerTestResource end describe Puppet::Parser::Compiler do + include PuppetSpec::Files + def resource(type, title) Puppet::Parser::Resource.new(type, title, :scope => @scope) end @@ -177,8 +179,8 @@ describe Puppet::Parser::Compiler do @node.stubs(:parameters).returns(params) compile_stub(:set_node_parameters) @compiler.compile - @compiler.topscope.lookupvar("a").should == "b" - @compiler.topscope.lookupvar("c").should == "d" + @compiler.topscope['a'].should == "b" + @compiler.topscope['c'].should == "d" end it "should set the client and server versions on the catalog" do @@ -413,7 +415,7 @@ describe Puppet::Parser::Compiler do end it "should fail to add resources that conflict with existing resources" do - path = Puppet.features.posix? ? "/foo" : "C:/foo" + path = make_absolute("/foo") file1 = Puppet::Type.type(:file).new :path => path file2 = Puppet::Type.type(:file).new :path => path @@ -571,42 +573,62 @@ describe Puppet::Parser::Compiler do @compiler.evaluate_classes(%w{myclass}, @scope) end - it "should ensure each node class hash is in catalog and have appropriate parameters", :'fails_on_ruby_1.9.2' => true do - klasses = {'foo'=>{'1'=>'one'}, 'bar::foo'=>{'2'=>'two'}, 'bar'=>{'1'=> [1,2,3], '2'=>{'foo'=>'bar'}}} - @node.classes = klasses - ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') - klasses.each do |name, params| - klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj}) + describe "and the classes are specified as a hash with parameters" do + before do + @node.classes = {} + @ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') + end + + # Define the given class with default parameters + def define_class(name, parameters) + @node.classes[name] = parameters + klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => @ast_obj, '2' => @ast_obj}) @compiler.topscope.known_resource_types.add klass end - catalog = @compiler.compile - catalog.classes.should =~ ['foo', 'bar::foo', 'settings', 'bar'] - r1 = catalog.resources.detect {|r| r.title == 'Foo' } - r1.to_hash.should == {:'1' => 'one', :'2' => 'foo'} - r1.tags. should =~ ['class', 'foo'] + def compile + @catalog = @compiler.compile + end - r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' } - r2.to_hash.should == {:'1' => 'foo', :'2' => 'two'} - r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo'] + it "should record which classes are evaluated" do + classes = {'foo'=>{}, 'bar::foo'=>{}, 'bar'=>{}} + classes.each { |c, params| define_class(c, params) } + compile() + classes.each { |name, p| @catalog.classes.should include(name) } + end - r2 = catalog.resources.detect {|r| r.title == 'Bar' } - r2.to_hash.should == {:'1' => [1,2,3], :'2' => {'foo'=>'bar'}} - r2.tags.should =~ ['class', 'bar'] - end + it "should provide default values for parameters that have no values specified" do + define_class('foo', {}) + compile() + @catalog.resource(:class, 'foo')['1'].should == "foo" + end - it "should ensure each node class is in catalog and has appropriate tags", :'fails_on_ruby_1.9.2' => true do - klasses = ['bar::foo'] - @node.classes = klasses - ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') - klasses.each do |name| - klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj}) - @compiler.topscope.known_resource_types.add klass + it "should use any provided values" do + define_class('foo', {'1' => 'real_value'}) + compile() + @catalog.resource(:class, 'foo')['1'].should == "real_value" + end + + it "should support providing some but not all values" do + define_class('foo', {'1' => 'real_value'}) + compile() + @catalog.resource(:class, 'Foo')['1'].should == "real_value" + @catalog.resource(:class, 'Foo')['2'].should == "foo" end - catalog = @compiler.compile - r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' } - r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo'] + it "should ensure each node class is in catalog and has appropriate tags", :'fails_on_ruby_1.9.2' => true do + klasses = ['bar::foo'] + @node.classes = klasses + ast_obj = Puppet::Parser::AST::String.new(:value => 'foo') + klasses.each do |name| + klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj}) + @compiler.topscope.known_resource_types.add klass + end + catalog = @compiler.compile + + r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' } + r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo'] + end end it "should fail if required parameters are missing" do @@ -614,15 +636,15 @@ describe Puppet::Parser::Compiler do @node.classes = klass klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'1' => nil, '2' => nil}) @compiler.topscope.known_resource_types.add klass - lambda { @compiler.compile }.should raise_error Puppet::ParseError, "Must pass 2 to Class[Foo]" + lambda { @compiler.compile }.should raise_error(Puppet::ParseError, "Must pass 2 to Class[Foo]") end it "should fail if invalid parameters are passed" do klass = {'foo'=>{'3'=>'one'}} @node.classes = klass - klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'1' => nil, '2' => nil}) + klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {}) @compiler.topscope.known_resource_types.add klass - lambda { @compiler.compile }.should raise_error Puppet::ParseError, "Invalid parameter 3" + lambda { @compiler.compile }.should raise_error(Puppet::ParseError, "Invalid parameter 3") end it "should ensure class is in catalog without params" do diff --git a/spec/unit/parser/files_spec.rb b/spec/unit/parser/files_spec.rb index 04777f0ec..1bf75e623 100755 --- a/spec/unit/parser/files_spec.rb +++ b/spec/unit/parser/files_spec.rb @@ -4,9 +4,10 @@ require 'spec_helper' require 'puppet/parser/files' describe Puppet::Parser::Files do + include PuppetSpec::Files before do - @basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath" + @basepath = make_absolute("/somepath") end it "should have a method for finding a template" do @@ -77,8 +78,9 @@ describe Puppet::Parser::Files do it "should accept relative templatedirs" do FileTest.stubs(:exist?).returns true Puppet[:templatedir] = "my/templates" - File.expects(:directory?).with(File.join(Dir.getwd,"my/templates")).returns(true) - Puppet::Parser::Files.find_template("mytemplate").should == File.join(Dir.getwd,"my/templates/mytemplate") + # We expand_path to normalize backslashes and slashes on Windows + File.expects(:directory?).with(File.expand_path(File.join(Dir.getwd,"my/templates"))).returns(true) + Puppet::Parser::Files.find_template("mytemplate").should == File.expand_path(File.join(Dir.getwd,"my/templates/mytemplate")) end it "should use the environment templatedir if no module is found and an environment is specified" do @@ -158,7 +160,8 @@ describe Puppet::Parser::Files do end it "should look for files relative to the current directory" do - cwd = Dir.getwd + # We expand_path to normalize backslashes and slashes on Windows + cwd = File.expand_path(Dir.getwd) Dir.expects(:glob).with("#{cwd}/foobar/init.pp").returns(["#{cwd}/foobar/init.pp"]) Puppet::Parser::Files.find_manifests("foobar/init.pp")[1].should == ["#{cwd}/foobar/init.pp"] end diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb index da76e75d0..94b1e7c68 100755 --- a/spec/unit/parser/functions/create_resources_spec.rb +++ b/spec/unit/parser/functions/create_resources_spec.rb @@ -78,7 +78,7 @@ notify{test:} end it 'should fail if defines are missing params' do @scope.function_create_resources(['foo', {'blah'=>{}}]) - lambda { @scope.compiler.compile }.should raise_error(Puppet::ParseError, 'Must pass one to Foo[blah] at line 1') + lambda { @scope.compiler.compile }.should raise_error(Puppet::ParseError, /Must pass one to Foo\[blah\]/) end it 'should be able to add multiple defines' do hash = {} diff --git a/spec/unit/parser/functions/extlookup_spec.rb b/spec/unit/parser/functions/extlookup_spec.rb index f68daaf3f..59ecf39c0 100755 --- a/spec/unit/parser/functions/extlookup_spec.rb +++ b/spec/unit/parser/functions/extlookup_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' require 'tempfile' describe "the extlookup function" do + include PuppetSpec::Files + before :all do Puppet::Parser::Functions.autoloader.loadall end @@ -64,30 +66,31 @@ describe "the extlookup function" do describe "should look in $extlookup_datadir for data files listed by $extlookup_precedence" do before do - @scope.stubs(:lookupvar).with('::extlookup_datadir').returns("/tmp") - File.open("/tmp/one.csv","w"){|one| one.puts "key,value1" } - File.open("/tmp/two.csv","w") do |two| + dir = tmpdir('extlookup_datadir') + @scope.stubs(:[]).with('::extlookup_datadir').returns(dir) + File.open(File.join(dir, "one.csv"),"w"){|one| one.puts "key,value1" } + File.open(File.join(dir, "two.csv"),"w") do |two| two.puts "key,value2" two.puts "key2,value_two" end end it "when the key is in the first file" do - @scope.stubs(:lookupvar).with('::extlookup_precedence').returns(["one","two"]) + @scope.stubs(:[]).with('::extlookup_precedence').returns(["one","two"]) result = @scope.function_extlookup([ "key" ]) result.should == "value1" end it "when the key is in the second file" do - @scope.stubs(:lookupvar).with('::extlookup_precedence').returns(["one","two"]) + @scope.stubs(:[]).with('::extlookup_precedence').returns(["one","two"]) result = @scope.function_extlookup([ "key2" ]) result.should == "value_two" end it "should not modify extlookup_precedence data" do variable = '%{fqdn}' - @scope.stubs(:lookupvar).with('::extlookup_precedence').returns([variable,"one"]) - @scope.stubs(:lookupvar).with('::fqdn').returns('myfqdn') + @scope.stubs(:[]).with('::extlookup_precedence').returns([variable,"one"]) + @scope.stubs(:[]).with('::fqdn').returns('myfqdn') result = @scope.function_extlookup([ "key" ]) variable.should == '%{fqdn}' end diff --git a/spec/unit/parser/functions/fqdn_rand_spec.rb b/spec/unit/parser/functions/fqdn_rand_spec.rb index 90fc0ef41..53c498453 100755 --- a/spec/unit/parser/functions/fqdn_rand_spec.rb +++ b/spec/unit/parser/functions/fqdn_rand_spec.rb @@ -8,6 +8,7 @@ describe "the fqdn_rand function" do before :each do @scope = Puppet::Parser::Scope.new + @scope[:fqdn] = "127.0.0.1" end it "should exist" do @@ -15,49 +16,40 @@ describe "the fqdn_rand function" do end it "should handle 0 arguments" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") lambda { @scope.function_fqdn_rand([]) }.should_not raise_error(Puppet::ParseError) end it "should handle 1 argument'}" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") lambda { @scope.function_fqdn_rand([3]) }.should_not raise_error(Puppet::ParseError) end (1..10).each { |n| it "should handle #{n} additional arguments" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") lambda { @scope.function_fqdn_rand([3,1,2,3,4,5,6,7,8,9,10][0..n]) }.should_not raise_error(Puppet::ParseError) end it "should handle #{n} additional string arguments" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") lambda { @scope.function_fqdn_rand([3,%w{ 1 2 3 4 5 6 7 8 9 10}].flatten[0..n]) }.should_not raise_error(Puppet::ParseError) end } it "should return a value less than max" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") @scope.function_fqdn_rand([3]).should satisfy {|n| n.to_i < 3 } end it "should return the same values on subsequent invocations for the same host" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice @scope.function_fqdn_rand([3,4]).should eql(@scope.function_fqdn_rand([3, 4])) end it "should return different sequences of value for different hosts" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") val1 = @scope.function_fqdn_rand([10000000,4]) - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.2") + @scope.expects(:[]).with("::fqdn").returns("127.0.0.2") val2 = @scope.function_fqdn_rand([10000000,4]) val1.should_not eql(val2) end it "should return different values for the same hosts with different seeds" do - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") val1 = @scope.function_fqdn_rand([10000000,4]) - @scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") val2 = @scope.function_fqdn_rand([10000000,42]) val1.should_not eql(val2) end diff --git a/spec/unit/parser/functions/sprintf_spec.rb b/spec/unit/parser/functions/sprintf_spec.rb index bd4863f23..3351c7fb3 100755 --- a/spec/unit/parser/functions/sprintf_spec.rb +++ b/spec/unit/parser/functions/sprintf_spec.rb @@ -30,7 +30,8 @@ describe "the sprintf function" do it "should format large floats" do result = @scope.function_sprintf(["%+.2e", "27182818284590451"]) - result.should(eql("+2.72e+16")) + str = Puppet.features.microsoft_windows? ? "+2.72e+016" : "+2.72e+16" + result.should(eql(str)) end it "should perform more complex formatting" do diff --git a/spec/unit/parser/functions_spec.rb b/spec/unit/parser/functions_spec.rb index 8240a184c..7eb6f299b 100755 --- a/spec/unit/parser/functions_spec.rb +++ b/spec/unit/parser/functions_spec.rb @@ -20,13 +20,17 @@ describe Puppet::Parser::Functions do end it "should have a method for returning an environment-specific module" do - Puppet::Parser::Functions.environment_module("myenv").should be_instance_of(Module) + Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.new("myenv")).should be_instance_of(Module) end it "should use the current default environment if no environment is provided" do Puppet::Parser::Functions.environment_module.should be_instance_of(Module) end + it "should be able to retrieve environment modules asked for by name rather than instance" do + Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.new("myenv")).should equal(Puppet::Parser::Functions.environment_module("myenv")) + end + describe "when calling newfunction" do before do @module = Module.new diff --git a/spec/unit/parser/resource_spec.rb b/spec/unit/parser/resource_spec.rb index 1190716d7..8513b8997 100755 --- a/spec/unit/parser/resource_spec.rb +++ b/spec/unit/parser/resource_spec.rb @@ -271,7 +271,7 @@ describe Puppet::Parser::Resource do end it "should not copy relationship metaparams when not in metaparam compatibility mode" do - @scope.setvar("require", "bar") + @scope['require'] = "bar" @resource.stubs(:metaparam_compatibility_mode?).returns false @resource.class.publicize_methods(:add_metaparams) { @resource.add_metaparams } @@ -280,7 +280,7 @@ describe Puppet::Parser::Resource do end it "should copy relationship metaparams when in metaparam compatibility mode" do - @scope.setvar("require", "bar") + @scope['require'] = "bar" @resource.stubs(:metaparam_compatibility_mode?).returns true @resource.class.publicize_methods(:add_metaparams) { @resource.add_metaparams } @@ -290,7 +290,7 @@ describe Puppet::Parser::Resource do it "should stack relationship metaparams when in metaparam compatibility mode" do @resource.set_parameter("require", "foo") - @scope.setvar("require", "bar") + @scope['require'] = "bar" @resource.stubs(:metaparam_compatibility_mode?).returns true @resource.class.publicize_methods(:add_metaparams) { @resource.add_metaparams } diff --git a/spec/unit/parser/scope_spec.rb b/spec/unit/parser/scope_spec.rb index 5308856ed..3c0d15cd7 100755 --- a/spec/unit/parser/scope_spec.rb +++ b/spec/unit/parser/scope_spec.rb @@ -42,12 +42,16 @@ describe Puppet::Parser::Scope do end it "should get its environment from its compiler" do - env = stub 'environment' + env = Puppet::Node::Environment.new compiler = stub 'compiler', :environment => env scope = Puppet::Parser::Scope.new :compiler => compiler scope.environment.should equal(env) end + it "should use the default environment if none is available" do + Puppet::Parser::Scope.new.environment.should equal(Puppet::Node::Environment.new) + end + it "should use the resource type collection helper to find its known resource types" do Puppet::Parser::Scope.ancestors.should include(Puppet::Resource::TypeCollectionHelper) end @@ -55,22 +59,18 @@ describe Puppet::Parser::Scope do describe "when initializing" do it "should extend itself with its environment's Functions module as well as the default" do env = Puppet::Node::Environment.new("myenv") + root = Puppet::Node::Environment.root compiler = stub 'compiler', :environment => env - mod = Module.new - root_mod = Module.new - Puppet::Parser::Functions.expects(:environment_module).with(Puppet::Node::Environment.root).returns root_mod - Puppet::Parser::Functions.expects(:environment_module).with(env).returns mod - Puppet::Parser::Scope.new(:compiler => compiler).singleton_class.ancestors.should be_include(mod) + scope = Puppet::Parser::Scope.new(:compiler => compiler) + scope.singleton_class.ancestors.should be_include(Puppet::Parser::Functions.environment_module(env)) + scope.singleton_class.ancestors.should be_include(Puppet::Parser::Functions.environment_module(root)) end - it "should extend itself with the default Functions module if it has no environment" do - mod = Module.new - Puppet::Parser::Functions.expects(:environment_module).with(Puppet::Node::Environment.root).returns(mod) - - Puppet::Parser::Functions.expects(:environment_module).with(nil).returns mod - - Puppet::Parser::Scope.new.singleton_class.ancestors.should be_include(mod) + it "should extend itself with the default Functions module if its environment is the default" do + root = Puppet::Node::Environment.root + scope = Puppet::Parser::Scope.new + scope.singleton_class.ancestors.should be_include(Puppet::Parser::Functions.environment_module(root)) end it "should remember if it is dynamic" do @@ -83,29 +83,55 @@ describe Puppet::Parser::Scope do end describe "when looking up a variable" do - it "should return ':undefined' for unset variables" do - @scope.lookupvar("var").should == :undefined + it "should support :lookupvar and :setvar for backward compatibility" do + @scope.setvar("var", "yep") + @scope.lookupvar("var").should == "yep" + end + + it "should return nil for unset variables" do + @scope["var"].should be_nil end it "should be able to look up values" do - @scope.setvar("var", "yep") - @scope.lookupvar("var").should == "yep" + @scope["var"] = "yep" + @scope["var"].should == "yep" end it "should be able to look up hashes" do - @scope.setvar("var", {"a" => "b"}) - @scope.lookupvar("var").should == {"a" => "b"} + @scope["var"] = {"a" => "b"} + @scope["var"].should == {"a" => "b"} end it "should be able to look up variables in parent scopes" do - @topscope.setvar("var", "parentval") - @scope.lookupvar("var").should == "parentval" + @topscope["var"] = "parentval" + @scope["var"].should == "parentval" end it "should prefer its own values to parent values" do - @topscope.setvar("var", "parentval") - @scope.setvar("var", "childval") - @scope.lookupvar("var").should == "childval" + @topscope["var"] = "parentval" + @scope["var"] = "childval" + @scope["var"].should == "childval" + end + + it "should be able to detect when variables are set" do + @scope["var"] = "childval" + @scope.should be_include("var") + end + + it "should be able to detect when variables are not set" do + @scope.should_not be_include("var") + end + + it "should support iteration over its variables" do + @scope["one"] = "two" + @scope["three"] = "four" + hash = {} + @scope.each { |name, value| hash[name] = value } + hash.should == {"one" => "two", "three" => "four" } + end + + it "should include Enumerable" do + @scope.singleton_class.ancestors.should be_include(Enumerable) end describe "and the variable is qualified" do @@ -133,84 +159,84 @@ describe Puppet::Parser::Scope do it "should be able to look up explicitly fully qualified variables from main" do other_scope = create_class_scope("") - other_scope.setvar("othervar", "otherval") + other_scope["othervar"] = "otherval" - @scope.lookupvar("::othervar").should == "otherval" + @scope["::othervar"].should == "otherval" end it "should be able to look up explicitly fully qualified variables from other scopes" do other_scope = create_class_scope("other") - other_scope.setvar("var", "otherval") + other_scope["var"] = "otherval" - @scope.lookupvar("::other::var").should == "otherval" + @scope["::other::var"].should == "otherval" end it "should be able to look up deeply qualified variables" do other_scope = create_class_scope("other::deep::klass") - other_scope.setvar("var", "otherval") + other_scope["var"] = "otherval" - @scope.lookupvar("other::deep::klass::var").should == "otherval" + @scope["other::deep::klass::var"].should == "otherval" end - it "should return ':undefined' for qualified variables that cannot be found in other classes" do + it "should return nil for qualified variables that cannot be found in other classes" do other_scope = create_class_scope("other::deep::klass") - @scope.lookupvar("other::deep::klass::var").should == :undefined + @scope["other::deep::klass::var"].should be_nil end - it "should warn and return ':undefined' for qualified variables whose classes have not been evaluated" do + it "should warn and return nil for qualified variables whose classes have not been evaluated" do klass = newclass("other::deep::klass") @scope.expects(:warning) - @scope.lookupvar("other::deep::klass::var").should == :undefined + @scope["other::deep::klass::var"].should be_nil end - it "should warn and return ':undefined' for qualified variables whose classes do not exist" do + it "should warn and return nil for qualified variables whose classes do not exist" do @scope.expects(:warning) - @scope.lookupvar("other::deep::klass::var").should == :undefined + @scope["other::deep::klass::var"].should be_nil end - it "should return ':undefined' when asked for a non-string qualified variable from a class that does not exist" do + it "should return nil when asked for a non-string qualified variable from a class that does not exist" do @scope.stubs(:warning) - @scope.lookupvar("other::deep::klass::var").should == :undefined + @scope["other::deep::klass::var"].should be_nil end - it "should return ':undefined' when asked for a non-string qualified variable from a class that has not been evaluated" do + it "should return nil when asked for a non-string qualified variable from a class that has not been evaluated" do @scope.stubs(:warning) klass = newclass("other::deep::klass") - @scope.lookupvar("other::deep::klass::var").should == :undefined + @scope["other::deep::klass::var"].should be_nil end end end - describe "when setvar is called with append=true" do - it "should raise error if the variable is already defined in this scope" do + describe "when variables are set with append=true" do + it "should raise an error if the variable is already defined in this scope" do @scope.setvar("var","1", :append => false) lambda { @scope.setvar("var","1", :append => true) }.should raise_error(Puppet::ParseError) end it "should lookup current variable value" do - @scope.expects(:lookupvar).with("var").returns("2") + @scope.expects(:[]).with("var").returns("2") @scope.setvar("var","1", :append => true) end it "should store the concatenated string '42'" do @topscope.setvar("var","4", :append => false) @scope.setvar("var","2", :append => true) - @scope.lookupvar("var").should == "42" + @scope["var"].should == "42" end it "should store the concatenated array [4,2]" do @topscope.setvar("var",[4], :append => false) @scope.setvar("var",[2], :append => true) - @scope.lookupvar("var").should == [4,2] + @scope["var"].should == [4,2] end it "should store the merged hash {a => b, c => d}" do @topscope.setvar("var",{"a" => "b"}, :append => false) @scope.setvar("var",{"c" => "d"}, :append => true) - @scope.lookupvar("var").should == {"a" => "b", "c" => "d"} + @scope["var"].should == {"a" => "b", "c" => "d"} end it "should raise an error when appending a hash with something other than another hash" do @@ -285,7 +311,7 @@ describe Puppet::Parser::Scope do it "should store the variable value" do @scope.setvar("1", :value, :ephemeral => true) - @scope.lookupvar("1").should == :value + @scope["1"].should == :value end it "should remove the variable value when unset_ephemeral_var is called" do @@ -294,17 +320,17 @@ describe Puppet::Parser::Scope do @scope.unset_ephemeral_var - @scope.lookupvar("1").should == :undefined + @scope["1"].should be_nil end it "should not remove classic variables when unset_ephemeral_var is called" do - @scope.setvar("myvar", :value1) + @scope['myvar'] = :value1 @scope.setvar("1", :value2, :ephemeral => true) @scope.stubs(:parent).returns(nil) @scope.unset_ephemeral_var - @scope.lookupvar("myvar").should == :value1 + @scope["myvar"].should == :value1 end it "should raise an error when setting it again" do @@ -325,7 +351,7 @@ describe Puppet::Parser::Scope do @scope.setvar("0", :earliest, :ephemeral => true) @scope.new_ephemeral @scope.setvar("0", :latest, :ephemeral => true) - @scope.lookupvar("0").should == :latest + @scope["0"].should == :latest end it "should be able to report the current level" do @@ -356,7 +382,7 @@ describe Puppet::Parser::Scope do @scope.setvar("1", :value1, :ephemeral => true) @scope.new_ephemeral @scope.setvar("0", :value2, :ephemeral => true) - @scope.lookupvar("1").should == :value1 + @scope["1"].should == :value1 end describe "when calling unset_ephemeral_var without a level" do @@ -367,7 +393,7 @@ describe Puppet::Parser::Scope do @scope.unset_ephemeral_var - @scope.lookupvar("1").should == :undefined + @scope["1"].should be_nil end end @@ -381,7 +407,7 @@ describe Puppet::Parser::Scope do @scope.unset_ephemeral_var(2) - @scope.lookupvar("1").should == :value2 + @scope["1"].should == :value2 end end end @@ -421,22 +447,22 @@ describe Puppet::Parser::Scope do describe "when unsetting variables" do it "should be able to unset normal variables" do - @scope.setvar("foo", "bar") + @scope["foo"] = "bar" @scope.unsetvar("foo") - @scope.lookupvar("foo").should == :undefined + @scope["foo"].should be_nil end it "should be able to unset ephemeral variables" do @scope.setvar("0", "bar", :ephemeral => true) @scope.unsetvar("0") - @scope.lookupvar("0").should == :undefined + @scope["0"].should be_nil end it "should not unset ephemeral variables in previous ephemeral scope" do @scope.setvar("0", "bar", :ephemeral => true) @scope.new_ephemeral @scope.unsetvar("0") - @scope.lookupvar("0").should == "bar" + @scope["0"].should == "bar" end end diff --git a/spec/unit/parser/templatewrapper_spec.rb b/spec/unit/parser/templatewrapper_spec.rb index 600293bbf..6080346fb 100755 --- a/spec/unit/parser/templatewrapper_spec.rb +++ b/spec/unit/parser/templatewrapper_spec.rb @@ -72,25 +72,23 @@ describe Puppet::Parser::TemplateWrapper do end it "should return the contents of a variable if called via method_missing" do - @scope.expects(:lookupvar).with { |name,options| name == "chicken"}.returns("is good") + @scope["chicken"] = "is good" tw = Puppet::Parser::TemplateWrapper.new(@scope) tw.chicken.should eql("is good") end it "should throw an exception if a variable is called via method_missing and it does not exist" do - @scope.expects(:lookupvar).with { |name,options| name == "chicken"}.returns(:undefined) tw = Puppet::Parser::TemplateWrapper.new(@scope) lambda { tw.chicken }.should raise_error(Puppet::ParseError) end it "should allow you to check whether a variable is defined with has_variable?" do - @scope.expects(:lookupvar).with { |name,options| name == "chicken"}.returns("is good") + @scope["chicken"] = "is good" tw = Puppet::Parser::TemplateWrapper.new(@scope) tw.has_variable?("chicken").should eql(true) end it "should allow you to check whether a variable is not defined with has_variable?" do - @scope.expects(:lookupvar).with { |name,options| name == "chicken"}.returns(:undefined) tw = Puppet::Parser::TemplateWrapper.new(@scope) tw.has_variable?("chicken").should eql(false) end diff --git a/spec/unit/parser/type_loader_spec.rb b/spec/unit/parser/type_loader_spec.rb index 9367b61c8..8b139613a 100755 --- a/spec/unit/parser/type_loader_spec.rb +++ b/spec/unit/parser/type_loader_spec.rb @@ -56,8 +56,8 @@ describe Puppet::Parser::TypeLoader do end it "should use the directory of the current file if one is set" do - Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == "/current" }.returns ["modname", %w{one}] - @loader.import("myfile", "/current/file") + Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == make_absolute("/current") }.returns ["modname", %w{one}] + @loader.import("myfile", make_absolute("/current/file")) end it "should pass the environment when looking for files" do @@ -71,15 +71,15 @@ describe Puppet::Parser::TypeLoader do end it "should parse each found file" do - Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{/one}] - @loader.expects(:parse_file).with("/one").returns(Puppet::Parser::AST::Hostclass.new('')) + Puppet::Parser::Files.expects(:find_manifests).returns ["modname", [make_absolute("/one")]] + @loader.expects(:parse_file).with(make_absolute("/one")).returns(Puppet::Parser::AST::Hostclass.new('')) @loader.import("myfile") end it "should make each file qualified before attempting to parse it" do Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{one}] - @loader.expects(:parse_file).with("/current/one").returns(Puppet::Parser::AST::Hostclass.new('')) - @loader.import("myfile", "/current/file") + @loader.expects(:parse_file).with(make_absolute("/current/one")).returns(Puppet::Parser::AST::Hostclass.new('')) + @loader.import("myfile", make_absolute("/current/file")) end it "should not attempt to import files that have already been imported" do @@ -102,7 +102,7 @@ describe Puppet::Parser::TypeLoader do @modulebase2 = File.join(@base, "second") FileUtils.mkdir_p(@modulebase2) - Puppet[:modulepath] = "#{@modulebase1}:#{@modulebase2}" + Puppet[:modulepath] = "#{@modulebase1}#{File::PATH_SEPARATOR}#{@modulebase2}" end def mk_module(basedir, name) diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb index 7728b5d40..99d4bc7c5 100755 --- a/spec/unit/property_spec.rb +++ b/spec/unit/property_spec.rb @@ -109,7 +109,7 @@ describe Puppet::Property do end end - describe "when creating an event" do + describe "when creating an event", :fails_on_windows => true do before do @event = Puppet::Transaction::Event.new diff --git a/spec/unit/provider/exec/shell_spec.rb b/spec/unit/provider/exec/shell_spec.rb index 90047b9d6..62036a79c 100755 --- a/spec/unit/provider/exec/shell_spec.rb +++ b/spec/unit/provider/exec/shell_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' provider_class = Puppet::Type.type(:exec).provider(:shell) -describe provider_class do +describe provider_class, :unless => Puppet.features.microsoft_windows? do before :each do @resource = Puppet::Resource.new(:exec, 'foo') @provider = provider_class.new(@resource) diff --git a/spec/unit/provider/macauthorization_spec.rb b/spec/unit/provider/macauthorization_spec.rb index a76f917f7..dbe36a04b 100755 --- a/spec/unit/provider/macauthorization_spec.rb +++ b/spec/unit/provider/macauthorization_spec.rb @@ -106,6 +106,11 @@ describe provider_class do end it "should call the internal method set_right" do + @provider.expects(:execute).with { |cmds, args| + cmds.include?("read") and + cmds.include?(@authname) and + args[:combine] == false + }.once @provider.expects(:set_right) @provider.flush end diff --git a/spec/unit/provider/mount/parsed_spec.rb b/spec/unit/provider/mount/parsed_spec.rb index 7831dae3a..fdee2efab 100755 --- a/spec/unit/provider/mount/parsed_spec.rb +++ b/spec/unit/provider/mount/parsed_spec.rb @@ -8,7 +8,7 @@ require 'shared_behaviours/all_parsedfile_providers' provider_class = Puppet::Type.type(:mount).provider(:parsed) -describe provider_class do +describe provider_class, :fails_on_windows => true do before :each do @mount_class = Puppet::Type.type(:mount) diff --git a/spec/unit/provider/service/smf_spec.rb b/spec/unit/provider/service/smf_spec.rb index 5212d540a..fd7d50e3a 100755 --- a/spec/unit/provider/service/smf_spec.rb +++ b/spec/unit/provider/service/smf_spec.rb @@ -111,6 +111,7 @@ describe provider_class do it "should import the manifest if service is missing" do @provider.expects(:svccfg).with(:import, "/tmp/myservice.xml") @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "/system/myservice"], true) + @provider.expects(:svcs).with('-H', '-o', 'state,nstate', "/system/myservice").returns("online\t-") @provider.start end diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb new file mode 100755 index 000000000..2012a184a --- /dev/null +++ b/spec/unit/provider/service/windows_spec.rb @@ -0,0 +1,131 @@ +#!/usr/bin/env rspec +# +# Unit testing for the Windows service Provider +# + +require 'spec_helper' + +require 'win32/service' if Puppet.features.microsoft_windows? + +describe Puppet::Type.type(:service).provider(:windows), :if => Puppet.features.microsoft_windows? do + + before :each do + @resource = Puppet::Type.type(:service).new(:name => 'snmptrap', :provider => :windows) + + @config = Struct::ServiceConfigInfo.new + + @status = Struct::ServiceStatus.new + + Win32::Service.stubs(:config_info).with(@resource[:name]).returns(@config) + Win32::Service.stubs(:status).with(@resource[:name]).returns(@status) + end + + describe ".instances" do + it "should enumerate all services" do + list_of_services = ['snmptrap', 'svchost', 'sshd'].map { |s| stub('service', :service_name => s) } + Win32::Service.expects(:services).returns(list_of_services) + + described_class.instances.map(&:name).should =~ ['snmptrap', 'svchost', 'sshd'] + end + end + + describe "#start" do + it "should call out to the Win32::Service API to start the service" do + @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START) + + Win32::Service.expects(:start).with('snmptrap') + + @resource.provider.start + end + + it "should handle when Win32::Service.start raises a Win32::Service::Error" do + @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START) + + Win32::Service.expects(:start).with('snmptrap').raises( + Win32::Service::Error.new("The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.") + ) + + expect { @resource.provider.start }.to raise_error( + Puppet::Error, + /Cannot start snmptrap, error was: The service cannot be started, either/ + ) + end + + describe "when the service is disabled" do + before :each do + @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) + Win32::Service.stubs(:start).with(@resource[:name]) + end + + it "should refuse to start if not managing enable" do + expect { @resource.provider.start }.to raise_error(Puppet::Error, /Will not start disabled service/) + end + + it "should enable if managing enable and enable is true" do + @resource[:enable] = :true + + Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_AUTO_START).returns(Win32::Service) + + @resource.provider.start + end + + it "should manual start if managing enable and enable is false" do + @resource[:enable] = :false + + Win32::Service.expects(:configure).with('service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DEMAND_START).returns(Win32::Service) + + @resource.provider.start + end + end + end + + describe "#stop" do + it "should stop a running service" + it "should not try to stop an already stopped service" + end + + describe "#status" do + ['stopped', 'paused', 'stop pending', 'pause pending'].each do |state| + it "should report a #{state} service as stopped" do + @status.current_state = state + + @resource.provider.status.should == :stopped + end + end + + ["running", "continue pending", "start pending" ].each do |state| + it "should report a #{state} service as running" do + @status.current_state = state + + @resource.provider.status.should == :running + end + end + end + + describe "#enabled?" do + it "should report a service with a startup type of manual as manual" do + @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DEMAND_START) + + @resource.provider.enabled?.should == :manual + end + + it "should report a service with a startup type of disabled as false" do + @config.start_type = Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) + + @resource.provider.enabled?.should == :false + end + + # We need to guard this section explicitly since rspec will always + # construct all examples, even if it isn't going to run them. + if Puppet.features.microsoft_windows? + [Win32::Service::SERVICE_AUTO_START, Win32::Service::SERVICE_BOOT_START, Win32::Service::SERVICE_SYSTEM_START].each do |start_type_const| + start_type = Win32::Service.get_start_type(start_type_const) + it "should report a service with a startup type of '#{start_type}' as true" do + @config.start_type = start_type + + @resource.provider.enabled?.should == :true + end + end + end + end +end diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb index bd5e55a9e..a7798be54 100755 --- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb @@ -5,7 +5,7 @@ require 'puppet_spec/files' provider_class = Puppet::Type.type(:ssh_authorized_key).provider(:parsed) -describe provider_class do +describe provider_class, :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files before :each do @@ -77,7 +77,7 @@ describe provider_class do end end -describe provider_class do +describe provider_class, :unless => Puppet.features.microsoft_windows? do before :each do @resource = Puppet::Type.type(:ssh_authorized_key).new(:name => "foo", :user => "random_bob") diff --git a/spec/unit/provider/user/user_role_add_spec.rb b/spec/unit/provider/user/user_role_add_spec.rb index 5f2fc306e..c44fc5a65 100755 --- a/spec/unit/provider/user/user_role_add_spec.rb +++ b/spec/unit/provider/user/user_role_add_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' provider_class = Puppet::Type.type(:user).provider(:user_role_add) -describe provider_class do +describe provider_class, :fails_on_windows => true do before do @resource = stub("resource", :name => "myuser", :managehome? => nil) @resource.stubs(:should).returns "fakeval" diff --git a/spec/unit/provider/user/useradd_spec.rb b/spec/unit/provider/user/useradd_spec.rb index 724fc12c0..4265ee3a0 100755 --- a/spec/unit/provider/user/useradd_spec.rb +++ b/spec/unit/provider/user/useradd_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' provider_class = Puppet::Type.type(:user).provider(:useradd) -describe provider_class do +describe provider_class, :fails_on_windows => true do before do @resource = stub("resource", :name => "myuser", :managehome? => nil) @resource.stubs(:should).returns "fakeval" diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb index ebf523eab..f5f779fbf 100755 --- a/spec/unit/resource/catalog_spec.rb +++ b/spec/unit/resource/catalog_spec.rb @@ -2,30 +2,14 @@ require 'spec_helper' describe Puppet::Resource::Catalog, "when compiling" do + include PuppetSpec::Files before do - @basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath" + @basepath = make_absolute("/somepath") # stub this to not try to create state.yaml Puppet::Util::Storage.stubs(:store) end - it "should be an Expirer" do - Puppet::Resource::Catalog.ancestors.should be_include(Puppet::Util::Cacher::Expirer) - end - - it "should always be expired if it's not applying" do - @catalog = Puppet::Resource::Catalog.new("host") - @catalog.expects(:applying?).returns false - @catalog.should be_dependent_data_expired(Time.now) - end - - it "should not be expired if it's applying and the timestamp is late enough" do - @catalog = Puppet::Resource::Catalog.new("host") - @catalog.expire - @catalog.expects(:applying?).returns true - @catalog.should_not be_dependent_data_expired(Time.now) - end - it "should be able to write its list of classes to the class file" do @catalog = Puppet::Resource::Catalog.new("host") @@ -500,7 +484,7 @@ describe Puppet::Resource::Catalog, "when compiling" do lambda { @catalog.alias(@one, "other") }.should_not raise_error end - it "should create aliases for resources isomorphic resources whose names do not match their titles" do + it "should create aliases for isomorphic resources whose names do not match their titles" do resource = Puppet::Type::File.new(:title => "testing", :path => @basepath+"/something") @catalog.add_resource(resource) @@ -508,7 +492,7 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.resource(:file, @basepath+"/something").should equal(resource) end - it "should not create aliases for resources non-isomorphic resources whose names do not match their titles" do + it "should not create aliases for non-isomorphic resources whose names do not match their titles", :fails_on_windows => true do resource = Puppet::Type.type(:exec).new(:title => "testing", :command => "echo", :path => %w{/bin /usr/bin /usr/local/bin}) @catalog.add_resource(resource) @@ -524,11 +508,6 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.resource("notify", "other").should equal(@one) end - it "should ignore conflicting aliases that point to the aliased resource" do - @catalog.alias(@one, "other") - lambda { @catalog.alias(@one, "other") }.should_not raise_error - end - it "should fail to add an alias if the aliased name already exists" do @catalog.add_resource @one proc { @catalog.alias @two, "one" }.should raise_error(ArgumentError) @@ -582,13 +561,66 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.create_resource :file, args @catalog.resource("File[/yay]").should equal(resource) end + + describe "when adding resources with multiple namevars" do + before :each do + Puppet::Type.newtype(:multiple) do + newparam(:color, :namevar => true) + newparam(:designation, :namevar => true) + + def self.title_patterns + [ [ + /^(\w+) (\w+)$/, + [ + [:color, lambda{|x| x}], + [:designation, lambda{|x| x}] + ] + ] ] + end + end + end + + it "should add an alias using the uniqueness key" do + @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5") + + @catalog.add_resource(@resource) + @catalog.resource(:multiple, "some resource").must == @resource + @catalog.resource("Multiple[some resource]").must == @resource + @catalog.resource("Multiple[red 5]").must == @resource + end + + it "should conflict with a resource with the same uniqueness key" do + @resource = Puppet::Type.type(:multiple).new(:title => "some resource", :color => "red", :designation => "5") + @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "5") + + @catalog.add_resource(@resource) + expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "5"\].*resource \["Multiple", "red", "5"\] already defined/) + end + + it "should conflict when its uniqueness key matches another resource's title" do + path = make_absolute("/tmp/foo") + @resource = Puppet::Type.type(:file).new(:title => path) + @other = Puppet::Type.type(:file).new(:title => "another file", :path => path) + + @catalog.add_resource(@resource) + expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias File\[another file\] to \["#{Regexp.escape(path)}"\].*resource \["File", "#{Regexp.escape(path)}"\] already defined/) + end + + it "should conflict when its uniqueness key matches the uniqueness key derived from another resource's title" do + @resource = Puppet::Type.type(:multiple).new(:title => "red leader") + @other = Puppet::Type.type(:multiple).new(:title => "another resource", :color => "red", :designation => "leader") + + @catalog.add_resource(@resource) + expect { @catalog.add_resource(@other) }.to raise_error(ArgumentError, /Cannot alias Multiple\[another resource\] to \["red", "leader"\].*resource \["Multiple", "red", "leader"\] already defined/) + end + end end describe "when applying" do before :each do @catalog = Puppet::Resource::Catalog.new("host") - @transaction = mock 'transaction' + @transaction = Puppet::Transaction.new(@catalog) Puppet::Transaction.stubs(:new).returns(@transaction) @transaction.stubs(:evaluate) @transaction.stubs(:add_times) @@ -643,11 +675,6 @@ describe Puppet::Resource::Catalog, "when compiling" do @catalog.apply(:ignoreschedules => true) end - it "should expire cached data in the resources both before and after the transaction" do - @catalog.expects(:expire).times(2) - @catalog.apply - end - describe "host catalogs" do # super() doesn't work in the setup method for some reason @@ -808,8 +835,6 @@ describe Puppet::Resource::Catalog, "when compiling" do @real_indirection = Puppet::Resource::Catalog.indirection @indirection = stub 'indirection', :name => :catalog - - Puppet::Util::Cacher.expire end it "should use the value of the 'catalog_terminus' setting to determine its terminus class" do @@ -828,7 +853,6 @@ describe Puppet::Resource::Catalog, "when compiling" do end after do - Puppet::Util::Cacher.expire @real_indirection.reset_terminus_class end end diff --git a/spec/unit/resource/status_spec.rb b/spec/unit/resource/status_spec.rb index e5a9291db..18e3359df 100755 --- a/spec/unit/resource/status_spec.rb +++ b/spec/unit/resource/status_spec.rb @@ -4,14 +4,16 @@ require 'spec_helper' require 'puppet/resource/status' describe Puppet::Resource::Status do + include PuppetSpec::Files + before do - @resource = Puppet::Type.type(:file).new :path => "/my/file" + @resource = Puppet::Type.type(:file).new :path => make_absolute("/my/file") @status = Puppet::Resource::Status.new(@resource) end it "should compute type and title correctly" do @status.resource_type.should == "File" - @status.title.should == "/my/file" + @status.title.should == make_absolute("/my/file") end [:node, :file, :line, :current_values, :status, :evaluation_time].each do |attr| diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb index 352f767e4..416fbac42 100755 --- a/spec/unit/resource/type_spec.rb +++ b/spec/unit/resource/type_spec.rb @@ -238,9 +238,10 @@ describe Puppet::Resource::Type do describe "when setting its parameters in the scope" do before do - @scope = Puppet::Parser::Scope.new(:compiler => stub("compiler", :environment => Puppet::Node::Environment.new), :source => stub("source")) + @scope = Puppet::Parser::Scope.new @resource = Puppet::Parser::Resource.new(:foo, "bar", :scope => @scope) - @type = Puppet::Resource::Type.new(:hostclass, "foo") + @type = Puppet::Resource::Type.new(:definition, "foo") + @resource.environment.known_resource_types.add @type end ['module_name', 'name', 'title'].each do |variable| @@ -249,20 +250,20 @@ describe Puppet::Resource::Type do var = Puppet::Parser::AST::Variable.new({'value' => variable}) @type.set_arguments :foo => var @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar('foo').should == 'bar' + @scope['foo'].should == 'bar' end end # this test is to clarify a crazy edge case # if you specify these special names as params, the resource # will override the special variables - it "resource should override defaults" do + it "should allow the resource to override defaults" do @type.set_arguments :name => nil @resource[:name] = 'foobar' var = Puppet::Parser::AST::Variable.new({'value' => 'name'}) @type.set_arguments :foo => var @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar('foo').should == 'foobar' + @scope['foo'].should == 'foobar' end it "should set each of the resource's parameters as variables in the scope" do @@ -272,8 +273,8 @@ describe Puppet::Resource::Type do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("foo").should == "bar" - @scope.lookupvar("boo").should == "baz" + @scope['foo'].should == "bar" + @scope['boo'].should == "baz" end it "should set the variables as strings" do @@ -282,7 +283,7 @@ describe Puppet::Resource::Type do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("foo").should == "bar" + @scope['foo'].should == "bar" end it "should fail if any of the resource's parameters are not valid attributes" do @@ -293,13 +294,13 @@ describe Puppet::Resource::Type do end it "should evaluate and set its default values as variables for parameters not provided by the resource" do - @type.set_arguments :foo => stub("value", :safeevaluate => "something") + @type.set_arguments :foo => Puppet::Parser::AST::String.new(:value => "something") @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("foo").should == "something" + @scope['foo'].should == "something" end it "should set all default values as parameters in the resource" do - @type.set_arguments :foo => stub("value", :safeevaluate => "something") + @type.set_arguments :foo => Puppet::Parser::AST::String.new(:value => "something") @type.set_resource_parameters(@resource, @scope) @@ -308,7 +309,6 @@ describe Puppet::Resource::Type do it "should fail if the resource does not provide a value for a required argument" do @type.set_arguments :foo => nil - @resource.expects(:to_hash).returns({}) lambda { @type.set_resource_parameters(@resource, @scope) }.should raise_error(Puppet::ParseError) end @@ -316,13 +316,13 @@ describe Puppet::Resource::Type do it "should set the resource's title as a variable if not otherwise provided" do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("title").should == "bar" + @scope['title'].should == "bar" end it "should set the resource's name as a variable if not otherwise provided" do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("name").should == "bar" + @scope['name'].should == "bar" end it "should set its module name in the scope if available" do @@ -330,7 +330,7 @@ describe Puppet::Resource::Type do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("module_name").should == "mymod" + @scope["module_name"].should == "mymod" end it "should set its caller module name in the scope if available" do @@ -338,21 +338,20 @@ describe Puppet::Resource::Type do @type.set_resource_parameters(@resource, @scope) - @scope.lookupvar("caller_module_name").should == "mycaller" + @scope["caller_module_name"].should == "mycaller" end end describe "when describing and managing parent classes" do before do - @code = Puppet::Resource::TypeCollection.new("env") + @krt = Puppet::Node::Environment.new.known_resource_types @parent = Puppet::Resource::Type.new(:hostclass, "bar") - @code.add @parent + @krt.add @parent @child = Puppet::Resource::Type.new(:hostclass, "foo", :parent => "bar") - @code.add @child + @krt.add @child - @env = stub "environment", :known_resource_types => @code - @scope = stub "scope", :environment => @env, :namespaces => [""] + @scope = Puppet::Parser::Scope.new end it "should be able to define a parent" do @@ -365,16 +364,16 @@ describe Puppet::Resource::Type do it "should be able to find parent nodes" do parent = Puppet::Resource::Type.new(:node, "bar") - @code.add parent + @krt.add parent child = Puppet::Resource::Type.new(:node, "foo", :parent => "bar") - @code.add child + @krt.add child child.parent_type(@scope).should equal(parent) end it "should cache a reference to the parent type" do - @code.stubs(:hostclass).with("foo::bar").returns nil - @code.expects(:hostclass).with("bar").once.returns @parent + @krt.stubs(:hostclass).with("foo::bar").returns nil + @krt.expects(:hostclass).with("bar").once.returns @parent @child.parent_type(@scope) @child.parent_type end @@ -386,7 +385,7 @@ describe Puppet::Resource::Type do it "should be considered the child of a parent's parent" do @grandchild = Puppet::Resource::Type.new(:hostclass, "baz", :parent => "foo") - @code.add @grandchild + @krt.add @grandchild @child.parent_type(@scope) @grandchild.parent_type(@scope) @@ -396,7 +395,7 @@ describe Puppet::Resource::Type do it "should correctly state when it is not another type's child" do @notchild = Puppet::Resource::Type.new(:hostclass, "baz") - @code.add @notchild + @krt.add @notchild @notchild.should_not be_child_of(@parent) end @@ -406,14 +405,13 @@ describe Puppet::Resource::Type do before do @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode")) @scope = Puppet::Parser::Scope.new :compiler => @compiler - @resource = Puppet::Parser::Resource.new(:foo, "yay", :scope => @scope) + @resource = Puppet::Parser::Resource.new(:class, "foo", :scope => @scope) # This is so the internal resource lookup works, yo. @compiler.catalog.add_resource @resource - @known_resource_types = stub 'known_resource_types' - @resource.stubs(:known_resource_types).returns @known_resource_types @type = Puppet::Resource::Type.new(:hostclass, "foo") + @resource.environment.known_resource_types.add @type end it "should add hostclass names to the classes list" do diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 5c8e8dcf9..093532119 100755 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -3,9 +3,10 @@ require 'spec_helper' require 'puppet/resource' describe Puppet::Resource do + include PuppetSpec::Files before do - @basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath" + @basepath = make_absolute("/somepath") end [:catalog, :file, :line].each do |attr| @@ -272,6 +273,67 @@ describe Puppet::Resource do Puppet::Resource.new("file", "/foo").should_not == Puppet::Resource.new("file", "/f") end + describe "when setting default parameters" do + before do + @scope = Puppet::Parser::Scope.new + end + + it "should fail when asked to set default values and it is not a parser resource" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "default_param", :arguments => {"a" => Puppet::Parser::AST::String.new(:value => "default")}) + ) + resource = Puppet::Resource.new("default_param", "name") + lambda { resource.set_default_parameters(@scope) }.should raise_error(Puppet::DevError) + end + + it "should evaluate and set any default values when no value is provided" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "default_param", :arguments => {"a" => Puppet::Parser::AST::String.new(:value => "a_default_value")}) + ) + resource = Puppet::Parser::Resource.new("default_param", "name", :scope => Puppet::Parser::Scope.new) + resource.set_default_parameters(@scope) + resource["a"].should == "a_default_value" + end + + it "should skip attributes with no default value" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "no_default_param", :arguments => {"a" => Puppet::Parser::AST::String.new(:value => "a_default_value")}) + ) + resource = Puppet::Parser::Resource.new("no_default_param", "name", :scope => Puppet::Parser::Scope.new) + lambda { resource.set_default_parameters(@scope) }.should_not raise_error + end + + it "should return the list of default parameters set" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "default_param", :arguments => {"a" => Puppet::Parser::AST::String.new(:value => "a_default_value")}) + ) + resource = Puppet::Parser::Resource.new("default_param", "name", :scope => Puppet::Parser::Scope.new) + resource.set_default_parameters(@scope).should == [:a] + end + end + + describe "when validating all required parameters are present" do + it "should be able to validate that all required parameters are present" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "required_param", :arguments => {"a" => nil}) + ) + lambda { Puppet::Resource.new("required_param", "name").validate_complete }.should raise_error(Puppet::ParseError) + end + + it "should not fail when all required parameters are present" do + Puppet::Node::Environment.new.known_resource_types.add( + Puppet::Resource::Type.new(:definition, "no_required_param") + ) + resource = Puppet::Resource.new("no_required_param", "name") + resource["a"] = "meh" + lambda { resource.validate_complete }.should_not raise_error + end + + it "should not validate against builtin types" do + lambda { Puppet::Resource.new("file", "/bar").validate_complete }.should_not raise_error + end + end + describe "when referring to a resource with name canonicalization" do it "should canonicalize its own name" do res = Puppet::Resource.new("file", "/path/") diff --git a/spec/unit/semver_spec.rb b/spec/unit/semver_spec.rb new file mode 100644 index 000000000..0e0457b6e --- /dev/null +++ b/spec/unit/semver_spec.rb @@ -0,0 +1,187 @@ +require 'spec_helper' +require 'semver' + +describe SemVer do + describe '::valid?' do + it 'should validate basic version strings' do + %w[ 0.0.0 999.999.999 v0.0.0 v999.999.999 ].each do |vstring| + SemVer.valid?(vstring).should be_true + end + end + + it 'should validate special version strings' do + %w[ 0.0.0foo 999.999.999bar v0.0.0a v999.999.999beta ].each do |vstring| + SemVer.valid?(vstring).should be_true + end + end + + it 'should fail to validate invalid version strings' do + %w[ nope 0.0foo 999.999 x0.0.0 z.z.z 1.2.3-beta 1.x.y ].each do |vstring| + SemVer.valid?(vstring).should be_false + end + end + end + + describe '::find_matching' do + before :all do + @versions = %w[ + 0.0.1 + 0.0.2 + 1.0.0rc1 + 1.0.0rc2 + 1.0.0 + 1.0.1 + 1.1.0 + 1.1.1 + 1.1.2 + 1.1.3 + 1.1.4 + 1.2.0 + 1.2.1 + 2.0.0rc1 + ].map { |v| SemVer.new(v) } + end + + it 'should match exact versions by string' do + @versions.each do |version| + SemVer.find_matching(version, @versions).should == version + end + end + + it 'should return nil if no versions match' do + %w[ 3.0.0 2.0.0rc2 1.0.0alpha ].each do |v| + SemVer.find_matching(v, @versions).should be_nil + end + end + + it 'should find the greatest match for partial versions' do + SemVer.find_matching('1.0', @versions).should == 'v1.0.1' + SemVer.find_matching('1.1', @versions).should == 'v1.1.4' + SemVer.find_matching('1', @versions).should == 'v1.2.1' + SemVer.find_matching('2', @versions).should == 'v2.0.0rc1' + SemVer.find_matching('2.1', @versions).should == nil + end + + + it 'should find the greatest match for versions with placeholders' do + SemVer.find_matching('1.0.x', @versions).should == 'v1.0.1' + SemVer.find_matching('1.1.x', @versions).should == 'v1.1.4' + SemVer.find_matching('1.x', @versions).should == 'v1.2.1' + SemVer.find_matching('1.x.x', @versions).should == 'v1.2.1' + SemVer.find_matching('2.x', @versions).should == 'v2.0.0rc1' + SemVer.find_matching('2.x.x', @versions).should == 'v2.0.0rc1' + SemVer.find_matching('2.1.x', @versions).should == nil + end + end + + describe 'instantiation' do + it 'should raise an exception when passed an invalid version string' do + expect { SemVer.new('invalidVersion') }.to raise_exception ArgumentError + end + + it 'should populate the appropriate fields for a basic version string' do + version = SemVer.new('1.2.3') + version.major.should == 1 + version.minor.should == 2 + version.tiny.should == 3 + version.special.should == '' + end + + it 'should populate the appropriate fields for a special version string' do + version = SemVer.new('3.4.5beta6') + version.major.should == 3 + version.minor.should == 4 + version.tiny.should == 5 + version.special.should == 'beta6' + end + end + + describe '#matched_by?' do + subject { SemVer.new('v1.2.3beta') } + + describe 'should match against' do + describe 'literal version strings' do + it { should be_matched_by('1.2.3beta') } + + it { should_not be_matched_by('1.2.3alpha') } + it { should_not be_matched_by('1.2.4beta') } + it { should_not be_matched_by('1.3.3beta') } + it { should_not be_matched_by('2.2.3beta') } + end + + describe 'partial version strings' do + it { should be_matched_by('1.2.3') } + it { should be_matched_by('1.2') } + it { should be_matched_by('1') } + end + + describe 'version strings with placeholders' do + it { should be_matched_by('1.2.x') } + it { should be_matched_by('1.x.3') } + it { should be_matched_by('1.x.x') } + it { should be_matched_by('1.x') } + end + end + end + + describe 'comparisons' do + describe 'against a string' do + it 'should just work' do + SemVer.new('1.2.3').should == '1.2.3' + end + end + + describe 'against a symbol' do + it 'should just work' do + SemVer.new('1.2.3').should == :'1.2.3' + end + end + + describe 'on a basic version (v1.2.3)' do + subject { SemVer.new('v1.2.3') } + + it { should == SemVer.new('1.2.3') } + + # Different major versions + it { should > SemVer.new('0.2.3') } + it { should < SemVer.new('2.2.3') } + + # Different minor versions + it { should > SemVer.new('1.1.3') } + it { should < SemVer.new('1.3.3') } + + # Different tiny versions + it { should > SemVer.new('1.2.2') } + it { should < SemVer.new('1.2.4') } + + # Against special versions + it { should > SemVer.new('1.2.3beta') } + it { should < SemVer.new('1.2.4beta') } + end + + describe 'on a special version (v1.2.3beta)' do + subject { SemVer.new('v1.2.3beta') } + + it { should == SemVer.new('1.2.3beta') } + + # Same version, final release + it { should < SemVer.new('1.2.3') } + + # Different major versions + it { should > SemVer.new('0.2.3') } + it { should < SemVer.new('2.2.3') } + + # Different minor versions + it { should > SemVer.new('1.1.3') } + it { should < SemVer.new('1.3.3') } + + # Different tiny versions + it { should > SemVer.new('1.2.2') } + it { should < SemVer.new('1.2.4') } + + # Against special versions + it { should > SemVer.new('1.2.3alpha') } + it { should < SemVer.new('1.2.3beta2') } + end + end +end diff --git a/spec/unit/ssl/certificate_authority_spec.rb b/spec/unit/ssl/certificate_authority_spec.rb index 3aedfdc25..3c5780a43 100755 --- a/spec/unit/ssl/certificate_authority_spec.rb +++ b/spec/unit/ssl/certificate_authority_spec.rb @@ -5,7 +5,7 @@ require 'puppet/ssl/certificate_authority' describe Puppet::SSL::CertificateAuthority do after do - Puppet::Util::Cacher.expire + Puppet::SSL::CertificateAuthority.instance_variable_set(:@singleton_instance, nil) Puppet.settings.clearused end @@ -25,7 +25,7 @@ describe Puppet::SSL::CertificateAuthority do describe "when finding an existing instance" do describe "and the host is a CA host and the run_mode is master" do before do - Puppet.settings.stubs(:value).with(:ca).returns true + Puppet[:ca] = true Puppet.run_mode.stubs(:master?).returns true @ca = mock('ca') diff --git a/spec/unit/ssl/certificate_spec.rb b/spec/unit/ssl/certificate_spec.rb index 0b635f2bc..de5cedf59 100755 --- a/spec/unit/ssl/certificate_spec.rb +++ b/spec/unit/ssl/certificate_spec.rb @@ -89,6 +89,31 @@ describe Puppet::SSL::Certificate do @certificate.should respond_to(:content) end + describe "#alternate_names" do + before do + Puppet[:certdnsnames] = 'foo:bar:baz' + @csr = OpenSSL::X509::Request.new + @csr.subject = OpenSSL::X509::Name.new([['CN', 'quux']]) + @csr.public_key = OpenSSL::PKey::RSA.generate(Puppet[:keylength]).public_key + end + + it "should list all alternate names when the extension is present" do + cert = Puppet::SSL::CertificateFactory.new('server', @csr, @csr, 14).result + + @certificate = @class.from_s(cert.to_pem) + + @certificate.alternate_names.should =~ ['foo', 'bar', 'baz', 'quux'] + end + + it "should return an empty list of names if the extension is absent" do + cert = Puppet::SSL::CertificateFactory.new('client', @csr, @csr, 14).result + + @certificate = @class.from_s(cert.to_pem) + + @certificate.alternate_names.should == [] + end + end + it "should return a nil expiration if there is no actual certificate" do @certificate.stubs(:content).returns nil diff --git a/spec/unit/ssl/host_spec.rb b/spec/unit/ssl/host_spec.rb index c2d9690e6..226acdecd 100755 --- a/spec/unit/ssl/host_spec.rb +++ b/spec/unit/ssl/host_spec.rb @@ -5,15 +5,24 @@ require 'puppet/ssl/host' require 'puppet/sslcertificates' require 'puppet/sslcertificates/ca' -describe Puppet::SSL::Host do +# REMIND: Fails on windows because there is no user provider yet +describe Puppet::SSL::Host, :fails_on_windows => true do + include PuppetSpec::Files + before do Puppet::SSL::Host.indirection.terminus_class = :file + + # Get a safe temporary file + dir = tmpdir("ssl_host_testing") + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir + @host = Puppet::SSL::Host.new("myname") end after do # Cleaned out any cached localhost instance. - Puppet::Util::Cacher.expire + Puppet::SSL::Host.instance_variable_set(:@localhost, nil) Puppet::SSL::Host.ca_location = :none end @@ -82,16 +91,6 @@ describe Puppet::SSL::Host do Puppet::SSL::Host.localhost.should == Puppet::SSL::Host.localhost end - it "should be able to expire the cached instance" do - one = stub 'host1', :certificate => "eh", :key => 'foo' - two = stub 'host2', :certificate => "eh", :key => 'foo' - Puppet::SSL::Host.expects(:new).times(2).returns(one).then.returns(two) - - Puppet::SSL::Host.localhost.should equal(one) - Puppet::Util::Cacher.expire - Puppet::SSL::Host.localhost.should equal(two) - end - it "should be able to verify its certificate matches its key" do Puppet::SSL::Host.new("foo").should respond_to(:certificate_matches_key?) end @@ -711,7 +710,7 @@ describe Puppet::SSL::Host do end end - describe "when handling PSON" do + describe "when handling PSON", :unless => Puppet.features.microsoft_windows? do include PuppetSpec::Files before do diff --git a/spec/unit/ssl/inventory_spec.rb b/spec/unit/ssl/inventory_spec.rb index d8606b1b4..000f0a253 100755 --- a/spec/unit/ssl/inventory_spec.rb +++ b/spec/unit/ssl/inventory_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'puppet/ssl/inventory' -describe Puppet::SSL::Inventory do +describe Puppet::SSL::Inventory, :unless => Puppet.features.microsoft_windows? do before do @class = Puppet::SSL::Inventory end @@ -118,7 +118,7 @@ describe Puppet::SSL::Inventory do end end - describe "and formatting a certificate" do + describe "and formatting a certificate", :fails_on_windows => true do before do @cert = stub 'cert', :not_before => Time.now, :not_after => Time.now, :subject => "mycert", :serial => 15 end diff --git a/spec/unit/sslcertificates/ca_spec.rb b/spec/unit/sslcertificates/ca_spec.rb index eea246ba1..7a687b825 100755 --- a/spec/unit/sslcertificates/ca_spec.rb +++ b/spec/unit/sslcertificates/ca_spec.rb @@ -5,27 +5,23 @@ require 'puppet' require 'puppet/sslcertificates' require 'puppet/sslcertificates/ca' -describe Puppet::SSLCertificates::CA do +describe Puppet::SSLCertificates::CA, :unless => Puppet.features.microsoft_windows? do + include PuppetSpec::Files + before :all do @hosts = %w{host.domain.com Other.Testing.Com} end before :each do Puppet::Util::SUIDManager.stubs(:asuser).yields - file = Tempfile.new("ca_testing") - @dir = file.path - file.delete + dir = tmpdir("ca_testing") - Puppet.settings[:confdir] = @dir - Puppet.settings[:vardir] = @dir + Puppet.settings[:confdir] = dir + Puppet.settings[:vardir] = dir @ca = Puppet::SSLCertificates::CA.new end - after :each do - system("rm -rf #{@dir}") - end - describe 'when cleaning' do it 'should remove associated files' do dirs = [:csrdir, :signeddir, :publickeydir, :privatekeydir, :certdir] diff --git a/spec/unit/transaction/event_manager_spec.rb b/spec/unit/transaction/event_manager_spec.rb index d127d0391..37775997d 100755 --- a/spec/unit/transaction/event_manager_spec.rb +++ b/spec/unit/transaction/event_manager_spec.rb @@ -4,6 +4,8 @@ require 'spec_helper' require 'puppet/transaction/event_manager' describe Puppet::Transaction::EventManager do + include PuppetSpec::Files + describe "at initialization" do it "should require a transaction" do Puppet::Transaction::EventManager.new("trans").transaction.should == "trans" @@ -23,7 +25,7 @@ describe Puppet::Transaction::EventManager do before do @manager = Puppet::Transaction::EventManager.new(@transaction) - @resource = Puppet::Type.type(:file).new :path => "/my/file" + @resource = Puppet::Type.type(:file).new :path => make_absolute("/my/file") @graph = stub 'graph', :matching_edges => [], :resource => @resource @manager.stubs(:relationship_graph).returns @graph @@ -139,7 +141,7 @@ describe Puppet::Transaction::EventManager do @manager = Puppet::Transaction::EventManager.new(@transaction) @manager.stubs(:queue_events) - @resource = Puppet::Type.type(:file).new :path => "/my/file" + @resource = Puppet::Type.type(:file).new :path => make_absolute("/my/file") @event = Puppet::Transaction::Event.new(:name => :event, :resource => @resource) end diff --git a/spec/unit/transaction/event_spec.rb b/spec/unit/transaction/event_spec.rb index 0093baeb9..5f7f367b4 100755 --- a/spec/unit/transaction/event_spec.rb +++ b/spec/unit/transaction/event_spec.rb @@ -4,6 +4,8 @@ require 'spec_helper' require 'puppet/transaction/event' describe Puppet::Transaction::Event do + include PuppetSpec::Files + [:previous_value, :desired_value, :property, :resource, :name, :message, :file, :line, :tags, :audited].each do |attr| it "should support #{attr}", :'fails_on_ruby_1.9.2' => true do event = Puppet::Transaction::Event.new @@ -113,7 +115,7 @@ describe Puppet::Transaction::Event do describe "When converting to YAML" do it "should include only documented attributes" do - resource = Puppet::Type.type(:file).new(:title => "/tmp/foo") + resource = Puppet::Type.type(:file).new(:title => make_absolute("/tmp/foo")) event = Puppet::Transaction::Event.new(:source_description => "/my/param", :resource => resource, :file => "/foo.rb", :line => 27, :tags => %w{one two}, :desired_value => 7, :historical_value => 'Brazil', diff --git a/spec/unit/transaction/report_spec.rb b/spec/unit/transaction/report_spec.rb index 4b04cc157..0a6ab8b5f 100755 --- a/spec/unit/transaction/report_spec.rb +++ b/spec/unit/transaction/report_spec.rb @@ -103,10 +103,6 @@ describe Puppet::Transaction::Report do report.expects(:host).returns "me" report.name.should == "me" end - - after do - Puppet::Util::Cacher.expire - end end describe "when computing exit status" do @@ -154,7 +150,7 @@ describe Puppet::Transaction::Report do def add_statuses(count, type = :file) count.times do |i| - status = Puppet::Resource::Status.new(Puppet::Type.type(type).new(:title => "/my/path#{i}")) + status = Puppet::Resource::Status.new(Puppet::Type.type(type).new(:title => make_absolute("/my/path#{i}"))) yield status if block_given? @report.add_resource_status status end @@ -208,7 +204,7 @@ describe Puppet::Transaction::Report do end describe "for times" do - it "should provide the total amount of time for each resource type" do + it "should provide the total amount of time for each resource type", :fails_on_windows => true do add_statuses(3, :file) do |status| status.evaluation_time = 1 end diff --git a/spec/unit/transaction/resource_harness_spec.rb b/spec/unit/transaction/resource_harness_spec.rb index 20a42d27b..cadc31a0f 100755 --- a/spec/unit/transaction/resource_harness_spec.rb +++ b/spec/unit/transaction/resource_harness_spec.rb @@ -7,10 +7,14 @@ describe Puppet::Transaction::ResourceHarness do include PuppetSpec::Files before do + @mode_750 = Puppet.features.microsoft_windows? ? '644' : '750' + @mode_755 = Puppet.features.microsoft_windows? ? '644' : '755' + path = make_absolute("/my/file") + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) - @resource = Puppet::Type.type(:file).new :path => "/my/file" + @resource = Puppet::Type.type(:file).new :path => path @harness = Puppet::Transaction::ResourceHarness.new(@transaction) - @current_state = Puppet::Resource.new(:file, "/my/file") + @current_state = Puppet::Resource.new(:file, path) @resource.stubs(:retrieve).returns @current_state @status = Puppet::Resource::Status.new(@resource) Puppet::Resource::Status.stubs(:new).returns @status @@ -148,8 +152,8 @@ describe Puppet::Transaction::ResourceHarness do describe "when applying changes" do [false, true].each do |noop_mode|; describe (noop_mode ? "in noop mode" : "in normal mode") do - [nil, '750'].each do |machine_state|; describe (machine_state ? "with a file initially present" : "with no file initially present") do - [nil, '750', '755'].each do |yaml_mode| + [nil, @mode_750].each do |machine_state|; describe (machine_state ? "with a file initially present" : "with no file initially present") do + [nil, @mode_750, @mode_755].each do |yaml_mode| [nil, :file, :absent].each do |yaml_ensure|; describe "with mode=#{yaml_mode.inspect} and ensure=#{yaml_ensure.inspect} stored in state.yml" do [false, true].each do |auditing_ensure| [false, true].each do |auditing_mode| @@ -157,7 +161,7 @@ describe Puppet::Transaction::ResourceHarness do auditing.push(:mode) if auditing_mode auditing.push(:ensure) if auditing_ensure [nil, :file, :absent].each do |ensure_property| # what we set "ensure" to in the manifest - [nil, '750', '755'].each do |mode_property| # what we set "mode" to in the manifest + [nil, @mode_750, @mode_755].each do |mode_property| # what we set "mode" to in the manifest manifest_settings = {} manifest_settings[:audit] = auditing if !auditing.empty? manifest_settings[:ensure] = ensure_property if ensure_property diff --git a/spec/unit/transaction_spec.rb b/spec/unit/transaction_spec.rb index 4bf615803..3f34f65bd 100755 --- a/spec/unit/transaction_spec.rb +++ b/spec/unit/transaction_spec.rb @@ -11,8 +11,10 @@ def without_warnings end describe Puppet::Transaction do + include PuppetSpec::Files + before do - @basepath = Puppet.features.posix? ? "/what/ever" : "C:/tmp" + @basepath = make_absolute("/what/ever") @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) end @@ -87,13 +89,19 @@ describe Puppet::Transaction do @transaction.should_not be_any_failed end - it "should be possible to replace the report object" do + it "should use the provided report object" do report = Puppet::Transaction::Report.new("apply") - @transaction.report = report + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new, report) @transaction.report.should == report end + it "should create a report if none is provided" do + @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) + + @transaction.report.should be_kind_of Puppet::Transaction::Report + end + describe "when initializing" do it "should create an event manager" do @transaction = Puppet::Transaction.new(Puppet::Resource::Catalog.new) diff --git a/spec/unit/type/cron_spec.rb b/spec/unit/type/cron_spec.rb index 7bf92eb02..f2c18896b 100755 --- a/spec/unit/type/cron_spec.rb +++ b/spec/unit/type/cron_spec.rb @@ -1,7 +1,7 @@ #!/usr/bin/env rspec require 'spec_helper' -describe Puppet::Type.type(:cron) do +describe Puppet::Type.type(:cron), :unless => Puppet.features.microsoft_windows? do before do @class = Puppet::Type.type(:cron) diff --git a/spec/unit/type/exec_spec.rb b/spec/unit/type/exec_spec.rb index 47d1b8523..2861bb0e3 100755 --- a/spec/unit/type/exec_spec.rb +++ b/spec/unit/type/exec_spec.rb @@ -2,6 +2,8 @@ require 'spec_helper' describe Puppet::Type.type(:exec) do + include PuppetSpec::Files + def exec_tester(command, exitstatus = 0, rest = {}) @user_name = 'some_user_name' @group_name = 'some_group_name' @@ -30,12 +32,13 @@ describe Puppet::Type.type(:exec) do end before do - @command = Puppet.features.posix? ? '/bin/true whatever' : '"C:/Program Files/something.exe" whatever' + @command = make_absolute('/bin/true whatever') + @executable = make_absolute('/bin/true') + @bogus_cmd = make_absolute('/bogus/cmd') end - describe "when not stubbing the provider" do + describe "when not stubbing the provider", :fails_on_windows => true do before do - @executable = Puppet.features.posix? ? '/bin/true' : 'C:/Program Files/something.exe' File.stubs(:exists?).returns false File.stubs(:exists?).with(@executable).returns true File.stubs(:exists?).with('/bin/false').returns true @@ -139,17 +142,18 @@ describe Puppet::Type.type(:exec) do end end - it "should be able to autorequire files mentioned in the command" do + it "should be able to autorequire files mentioned in the command", :fails_on_windows => true do + foo = make_absolute('/bin/foo') catalog = Puppet::Resource::Catalog.new - tmp = Puppet::Type.type(:file).new(:name => "/bin/foo") + tmp = Puppet::Type.type(:file).new(:name => foo) catalog.add_resource tmp - execer = Puppet::Type.type(:exec).new(:name => "/bin/foo") + execer = Puppet::Type.type(:exec).new(:name => foo) catalog.add_resource execer catalog.relationship_graph.dependencies(execer).should == [tmp] end - describe "when handling the path parameter" do + describe "when handling the path parameter", :fails_on_windows => true do expect = %w{one two three four} { "an array" => expect, "a colon separated list" => "one:two:three:four", @@ -165,7 +169,7 @@ describe Puppet::Type.type(:exec) do end end - describe "when setting user" do + describe "when setting user", :fails_on_windows => true do it "should fail if we are not root" do Puppet.features.stubs(:root?).returns(false) expect { Puppet::Type.type(:exec).new(:name => @command, :user => 'input') }. @@ -184,7 +188,7 @@ describe Puppet::Type.type(:exec) do describe "when setting group" do shared_examples_for "exec[:group]" do ['one', 2, 'wheel', 4294967295, 4294967296].each do |value| - it "should accept '#{value}' without error or judgement" do + it "should accept '#{value}' without error or judgement", :fails_on_windows => true do type = Puppet::Type.type(:exec).new(:name => @command, :group => value) type[:group].should == value end @@ -205,7 +209,7 @@ describe Puppet::Type.type(:exec) do describe "when setting cwd" do it_should_behave_like "all path parameters", :cwd, :array => false do def instance(path) - Puppet::Type.type(:exec).new(:name => '/bin/true', :cwd => path) + Puppet::Type.type(:exec).new(:name => @executable, :cwd => path) end end end @@ -221,7 +225,7 @@ describe Puppet::Type.type(:exec) do if @param == :name then instance = Puppet::Type.type(:exec).new() else - instance = Puppet::Type.type(:exec).new(:name => "/bin/true") + instance = Puppet::Type.type(:exec).new(:name => @executable) end if valid then instance.provider.expects(:validatecmd).returns(true) @@ -246,7 +250,7 @@ describe Puppet::Type.type(:exec) do shared_examples_for "all exec command parameters that take arrays" do |param| describe "when given an array of inputs" do before :each do - @test = Puppet::Type.type(:exec).new(:name => "/bin/true") + @test = Puppet::Type.type(:exec).new(:name => @executable) end it "should accept the array when all commands return valid" do @@ -281,7 +285,7 @@ describe Puppet::Type.type(:exec) do describe "for simple parameters" do before :each do - @exec = Puppet::Type.type(:exec).new(:name => '/bin/true') + @exec = Puppet::Type.type(:exec).new(:name => @executable) end describe "when setting environment" do @@ -338,13 +342,15 @@ describe Puppet::Type.type(:exec) do end it "should convert timeout to a float" do - resource = Puppet::Type.type(:exec).new :command => "/bin/false", :timeout => "12" + command = make_absolute('/bin/false') + resource = Puppet::Type.type(:exec).new :command => command, :timeout => "12" resource[:timeout].should be_a(Float) resource[:timeout].should == 12.0 end it "should munge negative timeouts to 0.0" do - resource = Puppet::Type.type(:exec).new :command => "/bin/false", :timeout => "-12.0" + command = make_absolute('/bin/false') + resource = Puppet::Type.type(:exec).new :command => command, :timeout => "-12.0" resource.parameter(:timeout).value.should be_a(Float) resource.parameter(:timeout).value.should == 0.0 end @@ -442,7 +448,7 @@ describe Puppet::Type.type(:exec) do describe "when setting creates" do it_should_behave_like "all path parameters", :creates, :array => true do def instance(path) - Puppet::Type.type(:exec).new(:name => '/bin/true', :creates => path) + Puppet::Type.type(:exec).new(:name => @executable, :creates => path) end end end @@ -460,7 +466,7 @@ describe Puppet::Type.type(:exec) do describe "#check" do before :each do - @test = Puppet::Type.type(:exec).new(:name => "/bin/true") + @test = Puppet::Type.type(:exec).new(:name => @executable) end describe ":refreshonly" do @@ -525,8 +531,8 @@ describe Puppet::Type.type(:exec) do }.each do |param, sense| describe ":#{param}" do before :each do - @pass = "/magic/pass" - @fail = "/magic/fail" + @pass = make_absolute("/magic/pass") + @fail = make_absolute("/magic/fail") @pass_status = stub('status', :exitstatus => sense[:pass] ? 0 : 1) @fail_status = stub('status', :exitstatus => sense[:fail] ? 0 : 1) @@ -584,9 +590,9 @@ describe Puppet::Type.type(:exec) do end end - describe "#retrieve" do + describe "#retrieve", :fails_on_windows => true do before :each do - @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd") + @exec_resource = Puppet::Type.type(:exec).new(:name => @bogus_cmd) end it "should return :notrun when check_all_attributes returns true" do @@ -608,7 +614,7 @@ describe Puppet::Type.type(:exec) do describe "#output" do before :each do - @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd") + @exec_resource = Puppet::Type.type(:exec).new(:name => @bogus_cmd) end it "should return the provider's run output" do @@ -625,14 +631,15 @@ describe Puppet::Type.type(:exec) do describe "#refresh" do before :each do - @exec_resource = Puppet::Type.type(:exec).new(:name => "/bogus/cmd") + @exec_resource = Puppet::Type.type(:exec).new(:name => @bogus_cmd) end it "should call provider run with the refresh parameter if it is set" do + myother_bogus_cmd = make_absolute('/myother/bogus/cmd') provider = stub 'provider' @exec_resource.stubs(:provider).returns(provider) - @exec_resource.stubs(:[]).with(:refresh).returns('/myother/bogus/cmd') - provider.expects(:run).with('/myother/bogus/cmd') + @exec_resource.stubs(:[]).with(:refresh).returns(myother_bogus_cmd) + provider.expects(:run).with(myother_bogus_cmd) @exec_resource.refresh end @@ -641,7 +648,7 @@ describe Puppet::Type.type(:exec) do provider = stub 'provider' status = stubs "process_status" status.stubs(:exitstatus).returns("0") - provider.expects(:run).with('/bogus/cmd').returns(["silly output", status]) + provider.expects(:run).with(@bogus_cmd).returns(["silly output", status]) @exec_resource.stubs(:provider).returns(provider) @exec_resource.refresh diff --git a/spec/unit/type/file/checksum_spec.rb b/spec/unit/type/file/checksum_spec.rb index b47f617cc..30c4aba6d 100755 --- a/spec/unit/type/file/checksum_spec.rb +++ b/spec/unit/type/file/checksum_spec.rb @@ -4,7 +4,8 @@ require 'spec_helper' checksum = Puppet::Type.type(:file).attrclass(:checksum) describe checksum do before do - @resource = Puppet::Type.type(:file).new :path => "/foo/bar" + @path = Puppet.features.microsoft_windows? ? "c:/foo/bar" : "/foo/bar" + @resource = Puppet::Type.type(:file).new :path => @path @checksum = @resource.parameter(:checksum) end @@ -35,25 +36,25 @@ describe checksum do it "should use its current value when asked to sum a file's content" do @checksum.value = :md5lite - @checksum.expects(:md5lite_file).with("/foo/bar").returns "yay" - @checksum.sum_file("/foo/bar") + @checksum.expects(:md5lite_file).with(@path).returns "yay" + @checksum.sum_file(@path) end it "should use :md5 to sum a file when no value is set" do - @checksum.expects(:md5_file).with("/foo/bar").returns "yay" - @checksum.sum_file("/foo/bar") + @checksum.expects(:md5_file).with(@path).returns "yay" + @checksum.sum_file(@path) end it "should convert all sums to strings when summing files" do @checksum.value = :mtime - @checksum.expects(:mtime_file).with("/foo/bar").returns Time.now - lambda { @checksum.sum_file("/foo/bar") }.should_not raise_error + @checksum.expects(:mtime_file).with(@path).returns Time.now + lambda { @checksum.sum_file(@path) }.should_not raise_error end it "should return the summed contents of a file with a checksum label" do @resource[:checksum] = :md5 @checksum.expects(:md5_file).returns "mysum" - @checksum.sum_file("/foo/bar").should == "{md5}mysum" + @checksum.sum_file(@path).should == "{md5}mysum" end it "should return the summed contents of a stream with a checksum label" do diff --git a/spec/unit/type/file/content_spec.rb b/spec/unit/type/file/content_spec.rb index 7af5f9d83..04ec48555 100755 --- a/spec/unit/type/file/content_spec.rb +++ b/spec/unit/type/file/content_spec.rb @@ -254,6 +254,7 @@ describe content do @content.should = "{md5}foo" @content.resource.bucket.class.any_instance.stubs(:getfile).returns "foo" @content.write(@fh) + @fh.close end describe "from actual content" do @@ -298,7 +299,7 @@ describe content do end end - describe "from local source" do + describe "from local source", :fails_on_windows => true do before(:each) do @resource = Puppet::Type.type(:file).new :path => @filename, :backup => false @sourcename = tmpfile('source') diff --git a/spec/unit/type/file/selinux_spec.rb b/spec/unit/type/file/selinux_spec.rb index 2622948d0..f6e7451c7 100755 --- a/spec/unit/type/file/selinux_spec.rb +++ b/spec/unit/type/file/selinux_spec.rb @@ -1,12 +1,14 @@ #!/usr/bin/env rspec require 'spec_helper' - [:seluser, :selrole, :seltype, :selrange].each do |param| property = Puppet::Type.type(:file).attrclass(param) describe property do + include PuppetSpec::Files + before do - @resource = Puppet::Type.type(:file).new :path => "/my/file" + @path = make_absolute("/my/file") + @resource = Puppet::Type.type(:file).new :path => @path @sel = property.new :resource => @resource end @@ -18,14 +20,14 @@ require 'spec_helper' it "should retrieve nil for #{param} if there is no SELinux support" do stat = stub 'stat', :ftype => "foo" @resource.expects(:stat).returns stat - @sel.expects(:get_selinux_current_context).with("/my/file").returns nil + @sel.expects(:get_selinux_current_context).with(@path).returns nil @sel.retrieve.should be_nil end it "should retrieve #{param} if a SELinux context is found with a range" do stat = stub 'stat', :ftype => "foo" @resource.expects(:stat).returns stat - @sel.expects(:get_selinux_current_context).with("/my/file").returns "user_u:role_r:type_t:s0" + @sel.expects(:get_selinux_current_context).with(@path).returns "user_u:role_r:type_t:s0" expectedresult = case param when :seluser; "user_u" when :selrole; "role_r" @@ -38,7 +40,7 @@ require 'spec_helper' it "should retrieve #{param} if a SELinux context is found without a range" do stat = stub 'stat', :ftype => "foo" @resource.expects(:stat).returns stat - @sel.expects(:get_selinux_current_context).with("/my/file").returns "user_u:role_r:type_t" + @sel.expects(:get_selinux_current_context).with(@path).returns "user_u:role_r:type_t" expectedresult = case param when :seluser; "user_u" when :selrole; "role_r" @@ -49,13 +51,13 @@ require 'spec_helper' end it "should handle no default gracefully" do - @sel.expects(:get_selinux_default_context).with("/my/file").returns nil + @sel.expects(:get_selinux_default_context).with(@path).returns nil @sel.default.must be_nil end it "should be able to detect matchpathcon defaults" do @sel.stubs(:debug) - @sel.expects(:get_selinux_default_context).with("/my/file").returns "user_u:role_r:type_t:s0" + @sel.expects(:get_selinux_default_context).with(@path).returns "user_u:role_r:type_t:s0" expectedresult = case param when :seluser; "user_u" when :selrole; "role_r" @@ -73,7 +75,7 @@ require 'spec_helper' it "should be able to set a new context" do stat = stub 'stat', :ftype => "foo" @sel.should = %w{newone} - @sel.expects(:set_selinux_context).with("/my/file", ["newone"], param) + @sel.expects(:set_selinux_context).with(@path, ["newone"], param) @sel.sync end diff --git a/spec/unit/type/file/source_spec.rb b/spec/unit/type/file/source_spec.rb index 5665d323d..c696feaf8 100755 --- a/spec/unit/type/file/source_spec.rb +++ b/spec/unit/type/file/source_spec.rb @@ -3,9 +3,13 @@ require 'spec_helper' source = Puppet::Type.type(:file).attrclass(:source) describe Puppet::Type.type(:file).attrclass(:source) do + include PuppetSpec::Files + before do # Wow that's a messy interface to the resource. @resource = stub 'resource', :[]= => nil, :property => nil, :catalog => stub("catalog", :dependent_data_expired? => false), :line => 0, :file => '' + @foobar = make_absolute("/foo/bar") + @feebooz = make_absolute("/fee/booz") end it "should be a subclass of Parameter" do @@ -27,15 +31,7 @@ describe Puppet::Type.type(:file).attrclass(:source) do end end - it "should have a method for retrieving its metadata" do - source.new(:resource => @resource).must respond_to(:metadata) - end - - it "should have a method for setting its metadata" do - source.new(:resource => @resource).must respond_to(:metadata=) - end - - describe "when returning the metadata" do + describe "when returning the metadata", :fails_on_windows => true do before do @metadata = stub 'metadata', :source= => nil end @@ -52,58 +48,44 @@ describe Puppet::Type.type(:file).attrclass(:source) do end it "should collect its metadata using the Metadata class if it is not already set" do - @source = source.new(:resource => @resource, :value => "/foo/bar") - Puppet::FileServing::Metadata.indirection.expects(:find).with("/foo/bar").returns @metadata + @source = source.new(:resource => @resource, :value => @foobar) + Puppet::FileServing::Metadata.indirection.expects(:find).with(@foobar).returns @metadata @source.metadata end it "should use the metadata from the first found source" do metadata = stub 'metadata', :source= => nil - @source = source.new(:resource => @resource, :value => ["/foo/bar", "/fee/booz"]) - Puppet::FileServing::Metadata.indirection.expects(:find).with("/foo/bar").returns nil - Puppet::FileServing::Metadata.indirection.expects(:find).with("/fee/booz").returns metadata + @source = source.new(:resource => @resource, :value => [@foobar, @feebooz]) + Puppet::FileServing::Metadata.indirection.expects(:find).with(@foobar).returns nil + Puppet::FileServing::Metadata.indirection.expects(:find).with(@feebooz).returns metadata @source.metadata.should equal(metadata) end it "should store the found source as the metadata's source" do metadata = mock 'metadata' - @source = source.new(:resource => @resource, :value => "/foo/bar") - Puppet::FileServing::Metadata.indirection.expects(:find).with("/foo/bar").returns metadata + @source = source.new(:resource => @resource, :value => @foobar) + Puppet::FileServing::Metadata.indirection.expects(:find).with(@foobar).returns metadata - metadata.expects(:source=).with("/foo/bar") + metadata.expects(:source=).with(@foobar) @source.metadata end it "should fail intelligently if an exception is encountered while querying for metadata" do - @source = source.new(:resource => @resource, :value => "/foo/bar") - Puppet::FileServing::Metadata.indirection.expects(:find).with("/foo/bar").raises RuntimeError + @source = source.new(:resource => @resource, :value => @foobar) + Puppet::FileServing::Metadata.indirection.expects(:find).with(@foobar).raises RuntimeError @source.expects(:fail).raises ArgumentError lambda { @source.metadata }.should raise_error(ArgumentError) end it "should fail if no specified sources can be found" do - @source = source.new(:resource => @resource, :value => "/foo/bar") - Puppet::FileServing::Metadata.indirection.expects(:find).with("/foo/bar").returns nil + @source = source.new(:resource => @resource, :value => @foobar) + Puppet::FileServing::Metadata.indirection.expects(:find).with(@foobar).returns nil @source.expects(:fail).raises RuntimeError lambda { @source.metadata }.should raise_error(RuntimeError) end - - it "should expire the metadata appropriately" do - expirer = stub 'expired', :dependent_data_expired? => true - - metadata = stub 'metadata', :source= => nil - Puppet::FileServing::Metadata.indirection.expects(:find).with("/fee/booz").returns metadata - - @source = source.new(:resource => @resource, :value => ["/fee/booz"]) - @source.metadata = "foo" - - @source.stubs(:expirer).returns expirer - - @source.metadata.should_not == "foo" - end end it "should have a method for setting the desired values on the resource" do @@ -113,7 +95,7 @@ describe Puppet::Type.type(:file).attrclass(:source) do describe "when copying the source values" do before do - @resource = Puppet::Type.type(:file).new :path => "/foo/bar" + @resource = Puppet::Type.type(:file).new :path => @foobar @source = source.new(:resource => @resource) @metadata = stub 'metadata', :owner => 100, :group => 200, :mode => 123, :checksum => "{md5}asdfasdf", :ftype => "file" diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb index 3a01d09c1..65c7a091c 100755 --- a/spec/unit/type/file_spec.rb +++ b/spec/unit/type/file_spec.rb @@ -37,7 +37,6 @@ describe Puppet::Type.type(:file) do end describe "#write" do - it "should propagate failures encountered when renaming the temporary file" do File.stubs(:open) @@ -92,7 +91,6 @@ describe Puppet::Type.type(:file) do lambda { @file.write :NOTUSED }.should_not raise_error(Puppet::Error) end - end end @@ -152,255 +150,204 @@ describe Puppet::Type.type(:file) do end describe "when using POSIX filenames" do - describe "on POSIX systems" do - before do - Puppet.features.stubs(:posix?).returns(true) - Puppet.features.stubs(:microsoft_windows?).returns(false) - end - - it "should autorequire its parent directory" do - file = Puppet::Type::File.new(:path => "/foo/bar") - dir = Puppet::Type::File.new(:path => "/foo") - @catalog.add_resource file - @catalog.add_resource dir - reqs = file.autorequire - reqs[0].source.must == dir - reqs[0].target.must == file - end - - it "should autorequire its nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "/foo/bar/baz") - dir = Puppet::Type::File.new(:path => "/foo") - root = Puppet::Type::File.new(:path => "/") - @catalog.add_resource file - @catalog.add_resource dir - @catalog.add_resource root - reqs = file.autorequire - reqs.length.must == 1 - reqs[0].source.must == dir - reqs[0].target.must == file - end - - it "should not autorequire anything when there is no nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "/foo/bar/baz") - @catalog.add_resource file - file.autorequire.should be_empty - end - - it "should not autorequire its parent dir if its parent dir is itself" do - file = Puppet::Type::File.new(:path => "/") - @catalog.add_resource file - file.autorequire.should be_empty - end - - it "should remove trailing slashes" do - file = Puppet::Type::File.new(:path => "/foo/bar/baz/") - file[:path].should == "/foo/bar/baz" - end - - it "should remove double slashes" do - file = Puppet::Type::File.new(:path => "/foo/bar//baz") - file[:path].should == "/foo/bar/baz" - end + it "should autorequire its parent directory" do + file = Puppet::Type::File.new(:path => "/foo/bar") + dir = Puppet::Type::File.new(:path => "/foo") + @catalog.add_resource file + @catalog.add_resource dir + reqs = file.autorequire + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should remove trailing double slashes" do - file = Puppet::Type::File.new(:path => "/foo/bar/baz//") - file[:path].should == "/foo/bar/baz" - end + it "should autorequire its nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "/foo/bar/baz") + dir = Puppet::Type::File.new(:path => "/foo") + root = Puppet::Type::File.new(:path => "/") + @catalog.add_resource file + @catalog.add_resource dir + @catalog.add_resource root + reqs = file.autorequire + reqs.length.must == 1 + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should leave a single slash alone" do - file = Puppet::Type::File.new(:path => "/") - file[:path].should == "/" - end + it "should not autorequire anything when there is no nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "/foo/bar/baz") + @catalog.add_resource file + file.autorequire.should be_empty + end - it "should accept a double-slash at the start of the path" do - expect { - file = Puppet::Type::File.new(:path => "//tmp/xxx") - # REVISIT: This should be wrong, later. See the next test. - # --daniel 2011-01-31 - file[:path].should == '/tmp/xxx' - }.should_not raise_error - end + it "should not autorequire its parent dir if its parent dir is itself" do + file = Puppet::Type::File.new(:path => "/") + @catalog.add_resource file + file.autorequire.should be_empty + end - # REVISIT: This is pending, because I don't want to try and audit the - # entire codebase to make sure we get this right. POSIX treats two (and - # exactly two) '/' characters at the start of the path specially. - # - # See sections 3.2 and 4.11, which allow DomainOS to be all special like - # and still have the POSIX branding and all. --daniel 2011-01-31 - it "should preserve the double-slash at the start of the path" + it "should remove trailing slashes" do + file = Puppet::Type::File.new(:path => "/foo/bar/baz/") + file[:path].should == "/foo/bar/baz" end - describe "on Microsoft Windows systems" do - before do - Puppet.features.stubs(:posix?).returns(false) - Puppet.features.stubs(:microsoft_windows?).returns(true) - end + it "should remove double slashes" do + file = Puppet::Type::File.new(:path => "/foo/bar//baz") + file[:path].should == "/foo/bar/baz" + end - it "should refuse to work" do - lambda { Puppet::Type::File.new(:path => "/foo/bar") }.should raise_error(Puppet::Error) - end + it "should remove trailing double slashes" do + file = Puppet::Type::File.new(:path => "/foo/bar/baz//") + file[:path].should == "/foo/bar/baz" end - end - describe "when using Microsoft Windows filenames", :if => Puppet.features.microsoft_windows? do - describe "on Microsoft Windows systems" do - before do - Puppet.features.stubs(:posix?).returns(false) - Puppet.features.stubs(:microsoft_windows?).returns(true) - end + it "should leave a single slash alone" do + file = Puppet::Type::File.new(:path => "/") + file[:path].should == "/" + end - it "should autorequire its parent directory" do - file = Puppet::Type::File.new(:path => "X:/foo/bar") - dir = Puppet::Type::File.new(:path => "X:/foo") - @catalog.add_resource file - @catalog.add_resource dir - reqs = file.autorequire - reqs[0].source.must == dir - reqs[0].target.must == file - end + it "should accept a double-slash at the start of the path" do + expect { + file = Puppet::Type::File.new(:path => "//tmp/xxx") + # REVISIT: This should be wrong, later. See the next test. + # --daniel 2011-01-31 + file[:path].should == '/tmp/xxx' + }.should_not raise_error + end - it "should autorequire its nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "X:/foo/bar/baz") - dir = Puppet::Type::File.new(:path => "X:/foo") - root = Puppet::Type::File.new(:path => "X:/") - @catalog.add_resource file - @catalog.add_resource dir - @catalog.add_resource root - reqs = file.autorequire - reqs.length.must == 1 - reqs[0].source.must == dir - reqs[0].target.must == file - end + # REVISIT: This is pending, because I don't want to try and audit the + # entire codebase to make sure we get this right. POSIX treats two (and + # exactly two) '/' characters at the start of the path specially. + # + # See sections 3.2 and 4.11, which allow DomainOS to be all special like + # and still have the POSIX branding and all. --daniel 2011-01-31 + it "should preserve the double-slash at the start of the path" + end - it "should not autorequire anything when there is no nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "X:/foo/bar/baz") - @catalog.add_resource file - file.autorequire.should be_empty - end + describe "when using Microsoft Windows filenames" do + it "should autorequire its parent directory" do + file = Puppet::Type::File.new(:path => "X:/foo/bar") + dir = Puppet::Type::File.new(:path => "X:/foo") + @catalog.add_resource file + @catalog.add_resource dir + reqs = file.autorequire + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should not autorequire its parent dir if its parent dir is itself" do - file = Puppet::Type::File.new(:path => "X:/") - @catalog.add_resource file - file.autorequire.should be_empty - end + it "should autorequire its nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "X:/foo/bar/baz") + dir = Puppet::Type::File.new(:path => "X:/foo") + root = Puppet::Type::File.new(:path => "X:/") + @catalog.add_resource file + @catalog.add_resource dir + @catalog.add_resource root + reqs = file.autorequire + reqs.length.must == 1 + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should remove trailing slashes" do - file = Puppet::Type::File.new(:path => "X:/foo/bar/baz/") - file[:path].should == "X:/foo/bar/baz" - end + it "should not autorequire anything when there is no nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "X:/foo/bar/baz") + @catalog.add_resource file + file.autorequire.should be_empty + end - it "should remove double slashes" do - file = Puppet::Type::File.new(:path => "X:/foo/bar//baz") - file[:path].should == "X:/foo/bar/baz" - end + it "should not autorequire its parent dir if its parent dir is itself" do + file = Puppet::Type::File.new(:path => "X:/") + @catalog.add_resource file + file.autorequire.should be_empty + end - it "should remove trailing double slashes" do - file = Puppet::Type::File.new(:path => "X:/foo/bar/baz//") - file[:path].should == "X:/foo/bar/baz" - end + it "should remove trailing slashes" do + file = Puppet::Type::File.new(:path => "X:/foo/bar/baz/") + file[:path].should == "X:/foo/bar/baz" + end - it "should leave a drive letter with a slash alone", :'fails_on_ruby_1.9.2' => true do - file = Puppet::Type::File.new(:path => "X:/") - file[:path].should == "X:/" - end + it "should remove double slashes" do + file = Puppet::Type::File.new(:path => "X:/foo/bar//baz") + file[:path].should == "X:/foo/bar/baz" + end - it "should add a slash to a drive letter", :'fails_on_ruby_1.9.2' => true do - file = Puppet::Type::File.new(:path => "X:") - file[:path].should == "X:/" - end + it "should remove trailing double slashes" do + file = Puppet::Type::File.new(:path => "X:/foo/bar/baz//") + file[:path].should == "X:/foo/bar/baz" end - describe "on POSIX systems" do - before do - Puppet.features.stubs(:posix?).returns(true) - Puppet.features.stubs(:microsoft_windows?).returns(false) - end + it "should leave a drive letter with a slash alone", :'fails_on_ruby_1.9.2' => true do + file = Puppet::Type::File.new(:path => "X:/") + file[:path].should == "X:/" + end - it "should refuse to work" do - lambda { Puppet::Type::File.new(:path => "X:/foo/bar") }.should raise_error(Puppet::Error) - end + it "should not accept a drive letter without a slash", :'fails_on_ruby_1.9.2' => true do + lambda { Puppet::Type::File.new(:path => "X:") }.should raise_error(/File paths must be fully qualified/) end end - describe "when using UNC filenames" do - describe "on Microsoft Windows systems", :if => Puppet.features.microsoft_windows?, :'fails_on_ruby_1.9.2' => true do - before do - Puppet.features.stubs(:posix?).returns(false) - Puppet.features.stubs(:microsoft_windows?).returns(true) - end - - it "should autorequire its parent directory" do - file = Puppet::Type::File.new(:path => "//server/foo/bar") - dir = Puppet::Type::File.new(:path => "//server/foo") - @catalog.add_resource file - @catalog.add_resource dir - reqs = file.autorequire - reqs[0].source.must == dir - reqs[0].target.must == file - end - - it "should autorequire its nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/qux") - dir = Puppet::Type::File.new(:path => "//server/foo/bar") - root = Puppet::Type::File.new(:path => "//server/foo") - @catalog.add_resource file - @catalog.add_resource dir - @catalog.add_resource root - reqs = file.autorequire - reqs.length.must == 1 - reqs[0].source.must == dir - reqs[0].target.must == file - end + describe "when using UNC filenames", :'fails_on_ruby_1.9.2' => true do + before :each do + pending("UNC file paths not yet supported") + end - it "should not autorequire anything when there is no nearest ancestor directory" do - file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/qux") - @catalog.add_resource file - file.autorequire.should be_empty - end + it "should autorequire its parent directory" do + file = Puppet::Type::File.new(:path => "//server/foo/bar") + dir = Puppet::Type::File.new(:path => "//server/foo") + @catalog.add_resource file + @catalog.add_resource dir + reqs = file.autorequire + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should not autorequire its parent dir if its parent dir is itself" do - file = Puppet::Type::File.new(:path => "//server/foo") - @catalog.add_resource file - puts file.autorequire - file.autorequire.should be_empty - end + it "should autorequire its nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/qux") + dir = Puppet::Type::File.new(:path => "//server/foo/bar") + root = Puppet::Type::File.new(:path => "//server/foo") + @catalog.add_resource file + @catalog.add_resource dir + @catalog.add_resource root + reqs = file.autorequire + reqs.length.must == 1 + reqs[0].source.must == dir + reqs[0].target.must == file + end - it "should remove trailing slashes" do - file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/") - file[:path].should == "//server/foo/bar/baz" - end + it "should not autorequire anything when there is no nearest ancestor directory" do + file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/qux") + @catalog.add_resource file + file.autorequire.should be_empty + end - it "should remove double slashes" do - file = Puppet::Type::File.new(:path => "//server/foo/bar//baz") - file[:path].should == "//server/foo/bar/baz" - end + it "should not autorequire its parent dir if its parent dir is itself" do + file = Puppet::Type::File.new(:path => "//server/foo") + @catalog.add_resource file + puts file.autorequire + file.autorequire.should be_empty + end - it "should remove trailing double slashes" do - file = Puppet::Type::File.new(:path => "//server/foo/bar/baz//") - file[:path].should == "//server/foo/bar/baz" - end + it "should remove trailing slashes" do + file = Puppet::Type::File.new(:path => "//server/foo/bar/baz/") + file[:path].should == "//server/foo/bar/baz" + end - it "should remove a trailing slash from a sharename" do - file = Puppet::Type::File.new(:path => "//server/foo/") - file[:path].should == "//server/foo" - end + it "should remove double slashes" do + file = Puppet::Type::File.new(:path => "//server/foo/bar//baz") + file[:path].should == "//server/foo/bar/baz" + end - it "should not modify a sharename" do - file = Puppet::Type::File.new(:path => "//server/foo") - file[:path].should == "//server/foo" - end + it "should remove trailing double slashes" do + file = Puppet::Type::File.new(:path => "//server/foo/bar/baz//") + file[:path].should == "//server/foo/bar/baz" end - describe "on POSIX systems" do - before do - Puppet.features.stubs(:posix?).returns(true) - Puppet.features.stubs(:microsoft_windows?).returns(false) - end + it "should remove a trailing slash from a sharename" do + file = Puppet::Type::File.new(:path => "//server/foo/") + file[:path].should == "//server/foo" + end - it "should refuse to work" do - lambda { Puppet::Type::File.new(:path => "X:/foo/bar") }.should raise_error(Puppet::Error) - end + it "should not modify a sharename" do + file = Puppet::Type::File.new(:path => "//server/foo") + file[:path].should == "//server/foo" end end diff --git a/spec/unit/type/group_spec.rb b/spec/unit/type/group_spec.rb index afe28247a..3b6cac8bc 100755 --- a/spec/unit/type/group_spec.rb +++ b/spec/unit/type/group_spec.rb @@ -1,7 +1,7 @@ #!/usr/bin/env rspec require 'spec_helper' -describe Puppet::Type.type(:group) do +describe Puppet::Type.type(:group), :fails_on_windows => true do before do ENV["PATH"] += File::PATH_SEPARATOR + "/usr/sbin" unless ENV["PATH"].split(File::PATH_SEPARATOR).include?("/usr/sbin") @class = Puppet::Type.type(:group) diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb index 9ef76992a..3309cd267 100755 --- a/spec/unit/type/mount_spec.rb +++ b/spec/unit/type/mount_spec.rb @@ -1,7 +1,7 @@ #!/usr/bin/env rspec require 'spec_helper' -describe Puppet::Type.type(:mount) do +describe Puppet::Type.type(:mount), :fails_on_windows => true do it "should have a :refreshable feature that requires the :remount method" do Puppet::Type.type(:mount).provider_feature(:refreshable).methods.should == [:remount] end @@ -16,7 +16,7 @@ describe Puppet::Type.type(:mount) do end end -describe Puppet::Type.type(:mount), "when validating attributes" do +describe Puppet::Type.type(:mount), "when validating attributes", :fails_on_windows => true do [:name, :remounts, :provider].each do |param| it "should have a #{param} parameter" do Puppet::Type.type(:mount).attrtype(param).should == :param @@ -30,7 +30,7 @@ describe Puppet::Type.type(:mount), "when validating attributes" do end end -describe Puppet::Type.type(:mount)::Ensure, "when validating values" do +describe Puppet::Type.type(:mount)::Ensure, "when validating values", :fails_on_windows => true do before do @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil Puppet::Type.type(:mount).defaultprovider.expects(:new).returns(@provider) @@ -62,7 +62,7 @@ describe Puppet::Type.type(:mount)::Ensure, "when validating values" do end end -describe Puppet::Type.type(:mount)::Ensure do +describe Puppet::Type.type(:mount)::Ensure, :fails_on_windows => true do before :each do provider_properties = {} @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock, :property_hash => provider_properties @@ -279,7 +279,7 @@ describe Puppet::Type.type(:mount)::Ensure do end end -describe Puppet::Type.type(:mount), "when modifying an existing mount entry" do +describe Puppet::Type.type(:mount), "when modifying an existing mount entry", :fails_on_windows => true do before do @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock, :remount => nil Puppet::Type.type(:mount).defaultprovider.stubs(:new).returns(@provider) diff --git a/spec/unit/type/noop_metaparam_spec.rb b/spec/unit/type/noop_metaparam_spec.rb index f4241d417..7083dd037 100755 --- a/spec/unit/type/noop_metaparam_spec.rb +++ b/spec/unit/type/noop_metaparam_spec.rb @@ -4,9 +4,11 @@ require 'spec_helper' require 'puppet/type' describe Puppet::Type.type(:file).attrclass(:noop) do + include PuppetSpec::Files + before do Puppet.settings.stubs(:use) - @file = Puppet::Type.newfile :path => "/what/ever" + @file = Puppet::Type.newfile :path => make_absolute("/what/ever") end it "should accept true as a value" do diff --git a/spec/unit/type/resources_spec.rb b/spec/unit/type/resources_spec.rb index 48c068cfa..f596968d3 100755 --- a/spec/unit/type/resources_spec.rb +++ b/spec/unit/type/resources_spec.rb @@ -51,7 +51,7 @@ describe resources do @resources.generate.collect { |r| r.ref }.should_not include(@host1.ref) end - it "should not include the skipped users", :'fails_on_ruby_1.9.2' => true do + it "should not include the skipped users", :'fails_on_ruby_1.9.2' => true, :fails_on_windows => true do res = Puppet::Type.type(:resources).new :name => :user, :purge => true res.catalog = Puppet::Resource::Catalog.new @@ -72,7 +72,7 @@ describe resources do end end - describe "when the instance's do not have an ensure property" do + describe "when the instance's do not have an ensure property", :fails_on_windows => true do it "should not be included in the generated resources" do @no_ensure_resource = Puppet::Type.type(:exec).new(:name => '/usr/bin/env echo') Puppet::Type.type(:host).stubs(:instances).returns [@no_ensure_resource] diff --git a/spec/unit/type/service_spec.rb b/spec/unit/type/service_spec.rb index 40270e7c8..ab006a4be 100755 --- a/spec/unit/type/service_spec.rb +++ b/spec/unit/type/service_spec.rb @@ -57,6 +57,21 @@ describe Puppet::Type.type(:service), "when validating attribute values" do Puppet::Type.type(:service).new(:name => "yay", :enable => :false) end + it "should support :manual as a value to :enable on Windows" do + Puppet.features.stubs(:microsoft_windows?).returns true + + Puppet::Type.type(:service).new(:name => "yay", :enable => :manual) + end + + it "should not support :manual as a value to :enable when not on Windows" do + Puppet.features.stubs(:microsoft_windows?).returns false + + expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :manual) }.to raise_error( + Puppet::Error, + /Setting enable to manual is only supported on Microsoft Windows\./ + ) + end + it "should support :true as a value to :hasstatus" do Puppet::Type.type(:service).new(:name => "yay", :hasstatus => :true) end diff --git a/spec/unit/type/ssh_authorized_key_spec.rb b/spec/unit/type/ssh_authorized_key_spec.rb index 71b8a9ab0..db58dc9f3 100755 --- a/spec/unit/type/ssh_authorized_key_spec.rb +++ b/spec/unit/type/ssh_authorized_key_spec.rb @@ -3,7 +3,9 @@ require 'spec_helper' ssh_authorized_key = Puppet::Type.type(:ssh_authorized_key) -describe ssh_authorized_key do +describe ssh_authorized_key, :unless => Puppet.features.microsoft_windows? do + include PuppetSpec::Files + before do @class = Puppet::Type.type(:ssh_authorized_key) @@ -11,7 +13,7 @@ describe ssh_authorized_key do @class.stubs(:defaultprovider).returns(@provider_class) @class.stubs(:provider).returns(@provider_class) - @provider = stub 'provider', :class => @provider_class, :file_path => "/tmp/whatever", :clear => nil + @provider = stub 'provider', :class => @provider_class, :file_path => make_absolute("/tmp/whatever"), :clear => nil @provider_class.stubs(:new).returns(@provider) @catalog = Puppet::Resource::Catalog.new end diff --git a/spec/unit/type/tidy_spec.rb b/spec/unit/type/tidy_spec.rb index cb030634b..bf892e836 100755 --- a/spec/unit/type/tidy_spec.rb +++ b/spec/unit/type/tidy_spec.rb @@ -5,8 +5,10 @@ require 'puppet/file_bucket/dipper' tidy = Puppet::Type.type(:tidy) describe tidy do + include PuppetSpec::Files + before do - @basepath = Puppet.features.posix? ? "/what/ever" : "C:/tmp" + @basepath = make_absolute("/what/ever") Puppet.settings.stubs(:use) # for an unknown reason some of these specs fails when run individually diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb index 71c9e1857..f24fc8eef 100755 --- a/spec/unit/type/user_spec.rb +++ b/spec/unit/type/user_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' user = Puppet::Type.type(:user) -describe user do +describe user, :fails_on_windows => true do before do ENV["PATH"] += File::PATH_SEPARATOR + "/usr/sbin" unless ENV["PATH"].split(File::PATH_SEPARATOR).include?("/usr/sbin") @provider = stub 'provider' @@ -289,6 +289,14 @@ describe user do @password.change_to_s("other", "mypass").should_not be_include("mypass") end + it "should redact the password when displaying the old value" do + @password.is_to_s("currentpassword").should =~ /^\[old password hash redacted\]$/ + end + + it "should redact the password when displaying the new value" do + @password.should_to_s("newpassword").should =~ /^\[new password hash redacted\]$/ + end + it "should fail if a ':' is included in the password" do lambda { @password.should = "some:thing" }.should raise_error(Puppet::Error) end diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb index bbdaec3bc..218c626d2 100755 --- a/spec/unit/type_spec.rb +++ b/spec/unit/type_spec.rb @@ -1,10 +1,8 @@ #!/usr/bin/env rspec require 'spec_helper' -describe Puppet::Type do - it "should include the Cacher module" do - Puppet::Type.ancestors.should be_include(Puppet::Util::Cacher) - end +describe Puppet::Type, :'fails_on_windows' => true do + include PuppetSpec::Files it "should consider a parameter to be valid if it is a valid parameter" do Puppet::Type.type(:mount).should be_valid_parameter(:path) @@ -18,18 +16,6 @@ describe Puppet::Type do Puppet::Type.type(:mount).should be_valid_parameter(:noop) end - it "should use its catalog as its expirer" do - catalog = Puppet::Resource::Catalog.new - resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) - resource.catalog = catalog - resource.expirer.should equal(catalog) - end - - it "should do nothing when asked to expire when it has no catalog" do - resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) - lambda { resource.expire }.should_not raise_error - end - it "should be able to retrieve a property by name" do resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present) resource.property(:fstype).must be_instance_of(Puppet::Type.type(:mount).attrclass(:fstype)) @@ -309,7 +295,8 @@ describe Puppet::Type do end it "should use the Resource Type's namevar to determine how to find the name in the hash" do - Puppet::Type.type(:file).new(:path => "/yay").title.should == "/yay" + yay = make_absolute('/yay') + Puppet::Type.type(:file).new(:path => yay).title.should == yay end [:catalog].each do |param| @@ -387,7 +374,7 @@ describe Puppet::Type do end it "should delete the name via the namevar from the originally provided parameters" do - Puppet::Type.type(:file).new(:name => "/foo").original_parameters[:path].should be_nil + Puppet::Type.type(:file).new(:name => make_absolute('/foo')).original_parameters[:path].should be_nil end end @@ -471,7 +458,7 @@ describe Puppet::Type do end it "should provide a value for 'ensure' even if no desired value is provided" do - @resource = Puppet::Type.type(:file).new(:path => "/my/file/that/can't/exist") + @resource = Puppet::Type.type(:file).new(:path => make_absolute("/my/file/that/can't/exist")) end it "should not call retrieve on non-ensure properties if the resource is absent and should consider the property absent" do @@ -513,8 +500,8 @@ describe Puppet::Type do before do @catalog = Puppet::Resource::Catalog.new @container = Puppet::Type.type(:component).new(:name => "container") - @one = Puppet::Type.type(:file).new(:path => "/file/one") - @two = Puppet::Type.type(:file).new(:path => "/file/two") + @one = Puppet::Type.type(:file).new(:path => make_absolute("/file/one")) + @two = Puppet::Type.type(:file).new(:path => make_absolute("/file/two")) @catalog.add_resource @container @catalog.add_resource @one @@ -541,7 +528,9 @@ describe Puppet::Type do end end -describe Puppet::Type::RelationshipMetaparam do +describe Puppet::Type::RelationshipMetaparam, :fails_on_windows => true do + include PuppetSpec::Files + it "should be a subclass of Puppet::Parameter" do Puppet::Type::RelationshipMetaparam.superclass.should equal(Puppet::Parameter) end @@ -550,14 +539,15 @@ describe Puppet::Type::RelationshipMetaparam do Puppet::Type::RelationshipMetaparam.should respond_to(:subclasses) end - describe "when munging relationships" do + describe "when munging relationships", :'fails_on_windows' => true do before do - @resource = Puppet::Type.type(:mount).new :name => "/foo" + @path = make_absolute('/foo') + @resource = Puppet::Type.type(:mount).new :name => @path @metaparam = Puppet::Type.metaparamclass(:require).new :resource => @resource end it "should accept Puppet::Resource instances" do - ref = Puppet::Resource.new(:file, "/foo") + ref = Puppet::Resource.new(:file, @path) @metaparam.munge(ref)[0].should equal(ref) end @@ -585,18 +575,22 @@ describe Puppet::Type::RelationshipMetaparam do end end -describe Puppet::Type.metaparamclass(:check) do +describe Puppet::Type.metaparamclass(:check), :fails_on_windows => true do + include PuppetSpec::Files + it "should warn and create an instance of ':audit'" do - file = Puppet::Type.type(:file).new :path => "/foo" + file = Puppet::Type.type(:file).new :path => make_absolute('/foo') file.expects(:warning) file[:check] = :mode file[:audit].should == [:mode] end end -describe Puppet::Type.metaparamclass(:audit) do +describe Puppet::Type.metaparamclass(:audit), :fails_on_windows => true do + include PuppetSpec::Files + before do - @resource = Puppet::Type.type(:file).new :path => "/foo" + @resource = Puppet::Type.type(:file).new :path => make_absolute('/foo') end it "should default to being nil" do @@ -642,8 +636,9 @@ describe Puppet::Type.metaparamclass(:audit) do Puppet::Type.type(:file).stubs(:title_patterns).returns( [ [ /(.*)/, [ [:path, lambda{|x| x} ] ] ] ] ) - res = Puppet::Type.type(:file).new( :title => '/my/file', :path => '/my/file', :owner => 'root', :content => 'hello' ) - res.uniqueness_key.should == [ nil, 'root', '/my/file'] + myfile = make_absolute('/my/file') + res = Puppet::Type.type(:file).new( :title => myfile, :path => myfile, :owner => 'root', :content => 'hello' ) + res.uniqueness_key.should == [ nil, 'root', myfile] end end end diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb index d61b7689e..47ee54e1f 100755 --- a/spec/unit/util/autoload_spec.rb +++ b/spec/unit/util/autoload_spec.rb @@ -4,43 +4,47 @@ require 'spec_helper' require 'puppet/util/autoload' describe Puppet::Util::Autoload do + include PuppetSpec::Files + before do @autoload = Puppet::Util::Autoload.new("foo", "tmp") @autoload.stubs(:eachdir).yields "/my/dir" end - it "should use the Cacher module" do - Puppet::Util::Autoload.ancestors.should be_include(Puppet::Util::Cacher) - end - describe "when building the search path" do + before :each do + @dira = make_absolute('/a') + @dirb = make_absolute('/b') + @dirc = make_absolute('/c') + end + it "should collect all of the plugins and lib directories that exist in the current environment's module path" do Puppet.settings.expects(:value).with(:environment).returns "foo" - Puppet.settings.expects(:value).with(:modulepath, :foo).returns "/a:/b:/c" - Dir.expects(:entries).with("/a").returns %w{one two} - Dir.expects(:entries).with("/b").returns %w{one two} + Puppet.settings.expects(:value).with(:modulepath, :foo).returns "#{@dira}#{File::PATH_SEPARATOR}#{@dirb}#{File::PATH_SEPARATOR}#{@dirc}" + Dir.expects(:entries).with(@dira).returns %w{one two} + Dir.expects(:entries).with(@dirb).returns %w{one two} FileTest.stubs(:directory?).returns false - FileTest.expects(:directory?).with("/a").returns true - FileTest.expects(:directory?).with("/b").returns true - %w{/a/one/plugins /a/two/lib /b/one/plugins /b/two/lib}.each do |d| + FileTest.expects(:directory?).with(@dira).returns true + FileTest.expects(:directory?).with(@dirb).returns true + ["#{@dira}/one/plugins", "#{@dira}/two/lib", "#{@dirb}/one/plugins", "#{@dirb}/two/lib"].each do |d| FileTest.expects(:directory?).with(d).returns true end - @autoload.module_directories.should == %w{/a/one/plugins /a/two/lib /b/one/plugins /b/two/lib} + @autoload.module_directories.should == ["#{@dira}/one/plugins", "#{@dira}/two/lib", "#{@dirb}/one/plugins", "#{@dirb}/two/lib"] end it "should not look for lib directories in directories starting with '.'" do Puppet.settings.expects(:value).with(:environment).returns "foo" - Puppet.settings.expects(:value).with(:modulepath, :foo).returns "/a" - Dir.expects(:entries).with("/a").returns %w{. ..} - - FileTest.expects(:directory?).with("/a").returns true - FileTest.expects(:directory?).with("/a/./lib").never - FileTest.expects(:directory?).with("/a/./plugins").never - FileTest.expects(:directory?).with("/a/../lib").never - FileTest.expects(:directory?).with("/a/../plugins").never + Puppet.settings.expects(:value).with(:modulepath, :foo).returns @dira + Dir.expects(:entries).with(@dira).returns %w{. ..} + + FileTest.expects(:directory?).with(@dira).returns true + FileTest.expects(:directory?).with("#{@dira}/./lib").never + FileTest.expects(:directory?).with("#{@dira}/./plugins").never + FileTest.expects(:directory?).with("#{@dira}/../lib").never + FileTest.expects(:directory?).with("#{@dira}/../plugins").never @autoload.module_directories end diff --git a/spec/unit/util/backups_spec.rb b/spec/unit/util/backups_spec.rb index 611c19304..d2f36a6e6 100755 --- a/spec/unit/util/backups_spec.rb +++ b/spec/unit/util/backups_spec.rb @@ -4,28 +4,31 @@ require 'spec_helper' require 'puppet/util/backups' describe Puppet::Util::Backups do + include PuppetSpec::Files + before do FileTest.stubs(:exists?).returns true + @nosuchfile = make_absolute('/no/such/file') end describe "when backing up a file" do it "should noop if the file does not exist" do FileTest.expects(:exists?).returns false - file = Puppet::Type.type(:file).new(:name => '/no/such/file') + file = Puppet::Type.type(:file).new(:name => @nosuchfile) file.expects(:bucket).never file.perform_backup end it "should succeed silently if self[:backup] is false" do - file = Puppet::Type.type(:file).new(:name => '/no/such/file', :backup => false) + file = Puppet::Type.type(:file).new(:name => @nosuchfile, :backup => false) file.expects(:bucket).never FileTest.expects(:exists?).never file.perform_backup end it "a bucket should be used when provided" do - path = '/my/file' + path = make_absolute('/my/file') File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) @@ -39,7 +42,7 @@ describe Puppet::Util::Backups do end it "should propagate any exceptions encountered when backing up to a filebucket" do - path = '/my/file' + path = make_absolute('/my/file') File.stubs(:stat).with(path).returns(mock('stat', :ftype => 'file')) @@ -54,7 +57,7 @@ describe Puppet::Util::Backups do describe "and no filebucket is configured" do it "should remove any local backup if one exists" do - path = '/my/file' + path = make_absolute('/my/file') FileTest.stubs(:exists?).returns true backup = path + ".foo" @@ -69,7 +72,7 @@ describe Puppet::Util::Backups do end it "should fail when the old backup can't be removed" do - path = '/my/file' + path = make_absolute('/my/file') FileTest.stubs(:exists?).returns true backup = path + ".foo" @@ -84,7 +87,7 @@ describe Puppet::Util::Backups do end it "should not try to remove backups that don't exist" do - path = '/my/file' + path = make_absolute('/my/file') FileTest.stubs(:exists?).returns true backup = path + ".foo" @@ -99,7 +102,7 @@ describe Puppet::Util::Backups do end it "a copy should be created in the local directory" do - path = '/my/file' + path = make_absolute('/my/file') FileTest.stubs(:exists?).with(path).returns true FileUtils.expects(:cp_r).with(path, path + ".foo", :preserve => true) @@ -109,7 +112,7 @@ describe Puppet::Util::Backups do end it "should propagate exceptions if no backup can be created" do - path = '/my/file' + path = make_absolute('/my/file') FileTest.stubs(:exists?).with(path).returns true FileUtils.expects(:cp_r).raises ArgumentError @@ -122,13 +125,13 @@ describe Puppet::Util::Backups do describe "when backing up a directory" do it "a bucket should work when provided" do - path = '/my/dir' + path = make_absolute('/my/dir') File.stubs(:file?).returns true - Find.expects(:find).with(path).yields("/my/dir/file") + Find.expects(:find).with(path).yields(make_absolute("/my/dir/file")) bucket = stub('bucket', :name => "eh") - bucket.expects(:backup).with("/my/dir/file").returns true + bucket.expects(:backup).with(make_absolute("/my/dir/file")).returns true file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo') file.stubs(:bucket).returns bucket @@ -139,7 +142,7 @@ describe Puppet::Util::Backups do end it "should do nothing when recursing" do - path = '/my/dir' + path = make_absolute('/my/dir') bucket = stub('bucket', :name => "eh") bucket.expects(:backup).never diff --git a/spec/unit/util/cacher_spec.rb b/spec/unit/util/cacher_spec.rb index fe93afd2b..16414c858 100755 --- a/spec/unit/util/cacher_spec.rb +++ b/spec/unit/util/cacher_spec.rb @@ -3,182 +3,105 @@ require 'spec_helper' require 'puppet/util/cacher' -class ExpirerTest - include Puppet::Util::Cacher::Expirer -end - class CacheTest - @@init_count = 0 - - include Puppet::Util::Cacher - cached_attr(:instance_cache) { Time.now } -end + @@count = 0 -describe Puppet::Util::Cacher::Expirer do - before do - @expirer = ExpirerTest.new + def self.count + @@count end - it "should be able to test whether a timestamp is expired" do - @expirer.should respond_to(:dependent_data_expired?) - end - - it "should be able to expire all values" do - @expirer.should respond_to(:expire) - end - - it "should consider any value to be valid if it has never been expired" do - @expirer.should_not be_dependent_data_expired(Time.now) - end + include Puppet::Util::Cacher - it "should consider any value created after expiration to be expired" do - @expirer.expire - @expirer.should be_dependent_data_expired(Time.now - 1) + cached_attr(:instance_cache, 10) do + @@count += 1 + {:number => @@count} end end describe Puppet::Util::Cacher do - it "should be extended with the Expirer module" do - Puppet::Util::Cacher.singleton_class.ancestors.should be_include(Puppet::Util::Cacher::Expirer) + before :each do + CacheTest.set_attr_ttl(:instance_cache, 10) + @object = CacheTest.new end - it "should support defining cached attributes", :'fails_on_ruby_1.9.2' => true do - CacheTest.methods.should be_include("cached_attr") + it "should return a value calculated from the provided block" do + @object.instance_cache.should == {:number => CacheTest.count} end - it "should default to the Cacher module as its expirer" do - CacheTest.new.expirer.should equal(Puppet::Util::Cacher) + it "should return the cached value from the getter every time if the value is not expired" do + @object.instance_cache.should equal(@object.instance_cache) end - describe "when using cached attributes" do - before do - @expirer = ExpirerTest.new - @object = CacheTest.new + it "should regenerate and return a new value using the provided block if the value has expired" do + initial = @object.instance_cache - @object.stubs(:expirer).returns @expirer - end - - it "should create a getter for the cached attribute" do - @object.should respond_to(:instance_cache) - end - - it "should return a value calculated from the provided block" do - time = Time.now - Time.stubs(:now).returns time - @object.instance_cache.should equal(time) - end + # Ensure the value is expired immediately + CacheTest.set_attr_ttl(:instance_cache, -10) + @object.send(:set_expiration, :instance_cache) - it "should return the cached value from the getter every time if the value is not expired" do - @object.instance_cache.should equal(@object.instance_cache) - end - - it "should regenerate and return a new value using the provided block if the value has been expired" do - value = @object.instance_cache - @expirer.expire - @object.instance_cache.should_not equal(value) - end + @object.instance_cache.should_not equal(initial) + end - it "should be able to trigger expiration on its expirer" do - @expirer.expects(:expire) - @object.expire - end + it "should be able to cache false values" do + @object.expects(:init_instance_cache).once.returns false + @object.instance_cache.should be_false + @object.instance_cache.should be_false + end - it "should do nothing when asked to expire when no expirer is available" do - cacher = CacheTest.new - class << cacher - def expirer - nil - end - end - lambda { cacher.expire }.should_not raise_error - end + it "should cache values again after expiration" do + initial = @object.instance_cache - it "should be able to cache false values" do - @object.expects(:init_instance_cache).returns false - @object.instance_cache.should be_false - @object.instance_cache.should be_false - end + # Ensure the value is expired immediately + CacheTest.set_attr_ttl(:instance_cache, -10) + @object.send(:set_expiration, :instance_cache) - it "should cache values again after expiration" do - @object.instance_cache - @expirer.expire - @object.instance_cache.should equal(@object.instance_cache) - end + # Reset ttl so this new value doesn't get expired + CacheTest.set_attr_ttl(:instance_cache, 10) + after_expiration = @object.instance_cache - it "should always consider a value expired if it has no expirer" do - @object.stubs(:expirer).returns nil - @object.instance_cache.should_not equal(@object.instance_cache) - end + after_expiration.should_not == initial + @object.instance_cache.should == after_expiration + end - it "should allow writing of the attribute" do - @object.should respond_to(:instance_cache=) - end + it "should allow writing of the attribute" do + initial = @object.instance_cache - it "should correctly configure timestamps for expiration when the cached attribute is written to" do - @object.instance_cache = "foo" - @expirer.expire - @object.instance_cache.should_not == "foo" - end + @object.instance_cache = "another value" + @object.instance_cache.should == "another value" + end - it "should allow specification of a ttl for cached attributes" do - klass = Class.new do - include Puppet::Util::Cacher - end + it "should update the expiration when the cached attribute is set manually" do + # Freeze time + now = Time.now + Time.stubs(:now).returns now - klass.cached_attr(:myattr, :ttl => 5) { Time.now } + @object.instance_cache - klass.attr_ttl(:myattr).should == 5 - end + # Set expiration to something far in the future + CacheTest.set_attr_ttl(:instance_cache, 60) + @object.send(:set_expiration, :instance_cache) - it "should allow specification of a ttl as a string" do - klass = Class.new do - include Puppet::Util::Cacher - end + CacheTest.set_attr_ttl(:instance_cache, 10) - klass.cached_attr(:myattr, :ttl => "5") { Time.now } + @object.instance_cache = "foo" + @object.instance_variable_get(:@attr_expirations)[:instance_cache].should == now + 10 + end - klass.attr_ttl(:myattr).should == 5 + it "should allow specification of a ttl as a string" do + klass = Class.new do + include Puppet::Util::Cacher end - it "should fail helpfully if the ttl cannot be converted to an integer" do - klass = Class.new do - include Puppet::Util::Cacher - end - - lambda { klass.cached_attr(:myattr, :ttl => "yep") { Time.now } }.should raise_error(ArgumentError) - end + klass.cached_attr(:myattr, "5") { 10 } - it "should not check for a ttl expiration if the class does not support that method" do - klass = Class.new do - extend Puppet::Util::Cacher - end + klass.attr_ttl(:myattr).should == 5 + end - klass.singleton_class.cached_attr(:myattr) { "eh" } - klass.myattr + it "should fail helpfully if the ttl cannot be converted to an integer" do + klass = Class.new do + include Puppet::Util::Cacher end - it "should automatically expire cached attributes whose ttl has expired, even if no expirer is present" do - klass = Class.new do - def self.to_s - "CacheTestClass" - end - include Puppet::Util::Cacher - attr_accessor :value - end - - klass.cached_attr(:myattr, :ttl => 5) { self.value += 1; self.value } - - now = Time.now - later = Time.now + 15 - - instance = klass.new - instance.value = 0 - instance.myattr.should == 1 - - Time.expects(:now).returns later - - # This call should get the new Time value, which should expire the old value - instance.myattr.should == 2 - end + lambda { klass.cached_attr(:myattr, "yep") { 10 } }.should raise_error(ArgumentError) end end diff --git a/spec/unit/util/execution_stub_spec.rb b/spec/unit/util/execution_stub_spec.rb index 34987689c..9cd15ca6a 100755 --- a/spec/unit/util/execution_stub_spec.rb +++ b/spec/unit/util/execution_stub_spec.rb @@ -16,7 +16,7 @@ describe Puppet::Util::ExecutionStub do Puppet::Util::ExecutionStub.current_value.should == nil end - it "should restore normal execution after 'reset' is called" do + it "should restore normal execution after 'reset' is called", :fails_on_windows => true do true_command = Puppet::Util.which('true') # Note: "true" exists at different paths in different OSes stub_call_count = 0 Puppet::Util::ExecutionStub.set do |command, options| diff --git a/spec/unit/util/log_spec.rb b/spec/unit/util/log_spec.rb index 1baa0d5af..39da4b010 100755 --- a/spec/unit/util/log_spec.rb +++ b/spec/unit/util/log_spec.rb @@ -4,6 +4,8 @@ require 'spec_helper' require 'puppet/util/log' describe Puppet::Util::Log do + include PuppetSpec::Files + it "should write a given message to the specified destination" do arraydest = [] Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(arraydest)) @@ -167,7 +169,7 @@ describe Puppet::Util::Log do describe "when setting the source as a RAL object" do it "should tag itself with any tags the source has" do - source = Puppet::Type.type(:file).new :path => "/foo/bar" + source = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar") log = Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => source) source.tags.each do |tag| log.tags.should be_include(tag) @@ -188,7 +190,7 @@ describe Puppet::Util::Log do end it "should copy over any file and line information" do - source = Puppet::Type.type(:file).new :path => "/foo/bar" + source = Puppet::Type.type(:file).new :path => make_absolute("/foo/bar") source.file = "/my/file" source.line = 50 log = Puppet::Util::Log.new(:level => "notice", :message => :foo, :source => source) diff --git a/spec/unit/util/logging_spec.rb b/spec/unit/util/logging_spec.rb index 6a77e70ef..2953f54a4 100755 --- a/spec/unit/util/logging_spec.rb +++ b/spec/unit/util/logging_spec.rb @@ -46,7 +46,7 @@ describe Puppet::Util::Logging do @logger.notice "foo" end - it "should use the path of any provided resource type" do + it "should use the path of any provided resource type", :fails_on_windows => true do resource = Puppet::Type.type(:mount).new :name => "foo" resource.expects(:path).returns "/path/to/mount".to_sym @@ -56,7 +56,7 @@ describe Puppet::Util::Logging do resource.notice "foo" end - it "should use the path of any provided resource parameter" do + it "should use the path of any provided resource parameter", :fails_on_windows => true do resource = Puppet::Type.type(:mount).new :name => "foo" param = resource.parameter(:name) diff --git a/spec/unit/util/network_device/config_spec.rb b/spec/unit/util/network_device/config_spec.rb index d69358a92..d9bd3d979 100755 --- a/spec/unit/util/network_device/config_spec.rb +++ b/spec/unit/util/network_device/config_spec.rb @@ -4,9 +4,11 @@ require 'spec_helper' require 'puppet/util/network_device/config' describe Puppet::Util::NetworkDevice::Config do + include PuppetSpec::Files + before(:each) do - Puppet[:deviceconfig] = "/dummy" - FileTest.stubs(:exists?).with("/dummy").returns(true) + Puppet[:deviceconfig] = make_absolute("/dummy") + FileTest.stubs(:exists?).with(make_absolute("/dummy")).returns(true) end describe "when initializing" do @@ -15,7 +17,7 @@ describe Puppet::Util::NetworkDevice::Config do end it "should use the deviceconfig setting as pathname" do - Puppet.expects(:[]).with(:deviceconfig).returns("/dummy") + Puppet.expects(:[]).with(:deviceconfig).returns(make_absolute("/dummy")) Puppet::Util::NetworkDevice::Config.new end diff --git a/spec/unit/util/rdoc/parser_spec.rb b/spec/unit/util/rdoc/parser_spec.rb index 92b50e09b..29e3298f0 100755 --- a/spec/unit/util/rdoc/parser_spec.rb +++ b/spec/unit/util/rdoc/parser_spec.rb @@ -8,6 +8,8 @@ require 'rdoc/options' require 'rdoc/rdoc' describe RDoc::Parser, :'fails_on_ruby_1.9.2' => true do + include PuppetSpec::Files + before :each do File.stubs(:stat).with("init.pp") @top_level = stub_everything 'toplevel', :file_relative_name => "init.pp" @@ -21,7 +23,7 @@ describe RDoc::Parser, :'fails_on_ruby_1.9.2' => true do Puppet::Parser::Parser.stubs(:new).returns(parser) parser.expects(:parse).returns(Puppet::Parser::AST::Hostclass.new('')).at_least_once parser.expects(:file=).with("module/manifests/init.pp") - parser.expects(:file=).with("/dev/null/manifests/site.pp") + parser.expects(:file=).with(make_absolute("/dev/null/manifests/site.pp")) @parser.scan end @@ -147,6 +149,10 @@ describe RDoc::Parser, :'fails_on_ruby_1.9.2' => true do File.stubs(:identical?).returns(false) @parser.split_module("/path/to/manifests/init.pp").should == RDoc::Parser::SITE end + + it "should handle windows paths with drive letters", :if => Puppet.features.microsoft_windows? do + @parser.split_module("C:/temp/init.pp").should == RDoc::Parser::SITE + end end describe "when parsing AST elements" do diff --git a/spec/unit/util/run_mode_spec.rb b/spec/unit/util/run_mode_spec.rb index c8d2b31f6..f2303ccc2 100755 --- a/spec/unit/util/run_mode_spec.rb +++ b/spec/unit/util/run_mode_spec.rb @@ -8,7 +8,9 @@ describe Puppet::Util::RunMode do it "should have confdir /etc/puppet when run as root" do Puppet.features.stubs(:root?).returns(true) - @run_mode.conf_dir.should == '/etc/puppet' + etcdir = Puppet.features.microsoft_windows? ? File.join(Dir::COMMON_APPDATA, "PuppetLabs", "puppet", "etc") : '/etc/puppet' + # REMIND: issue with windows backslashes + @run_mode.conf_dir.should == File.expand_path(etcdir) end it "should have confdir ~/.puppet when run as non-root" do @@ -19,7 +21,9 @@ describe Puppet::Util::RunMode do it "should have vardir /var/lib/puppet when run as root" do Puppet.features.stubs(:root?).returns(true) - @run_mode.var_dir.should == '/var/lib/puppet' + vardir = Puppet.features.microsoft_windows? ? File.join(Dir::COMMON_APPDATA, "PuppetLabs", "puppet", "var") : '/var/lib/puppet' + # REMIND: issue with windows backslashes + @run_mode.var_dir.should == File.expand_path(vardir) end it "should have vardir ~/.puppet/var when run as non-root" do diff --git a/spec/unit/util/settings/file_setting_spec.rb b/spec/unit/util/settings/file_setting_spec.rb index 489628a78..01d891f08 100755 --- a/spec/unit/util/settings/file_setting_spec.rb +++ b/spec/unit/util/settings/file_setting_spec.rb @@ -7,8 +7,10 @@ require 'puppet/util/settings/file_setting' describe Puppet::Util::Settings::FileSetting do FileSetting = Puppet::Util::Settings::FileSetting + include PuppetSpec::Files + before do - @basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath" + @basepath = make_absolute("/somepath") end describe "when determining whether the service user should be used" do @@ -165,7 +167,10 @@ describe Puppet::Util::Settings::FileSetting do it "should fully qualified returned files if necessary (#795)" do @settings.stubs(:value).with(:mydir).returns "myfile" - @file.to_resource.title.should == File.join(Dir.getwd, "myfile") + path = File.join(Dir.getwd, "myfile") + # Dir.getwd can return windows paths with backslashes, so we normalize them using expand_path + path = File.expand_path(path) if Puppet.features.microsoft_windows? + @file.to_resource.title.should == path end it "should set the mode on the file if a mode is provided" do diff --git a/spec/unit/util/settings_spec.rb b/spec/unit/util/settings_spec.rb index aa50c8f3a..76f229c0f 100755 --- a/spec/unit/util/settings_spec.rb +++ b/spec/unit/util/settings_spec.rb @@ -1,7 +1,10 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'ostruct' describe Puppet::Util::Settings do + include PuppetSpec::Files + describe "when specifying defaults" do before do @settings = Puppet::Util::Settings.new @@ -377,7 +380,7 @@ describe Puppet::Util::Settings do end it "should use its current ':config' value for the file to parse" do - myfile = Puppet.features.posix? ? "/my/file" : "C:/myfile" # do not stub expand_path here, as this leads to a stack overflow, when mocha tries to use it + myfile = make_absolute("/my/file") # do not stub expand_path here, as this leads to a stack overflow, when mocha tries to use it @settings[:config] = myfile File.expects(:read).with(myfile).returns "[main]" @@ -444,25 +447,27 @@ describe Puppet::Util::Settings do it "should support specifying all metadata (owner, group, mode) in the configuration file" do @settings.setdefaults :section, :myfile => ["/myfile", "a"] + otherfile = make_absolute("/other/file") text = "[main] - myfile = /other/file {owner = service, group = service, mode = 644} + myfile = #{otherfile} {owner = service, group = service, mode = 644} " @settings.expects(:read_file).returns(text) @settings.parse - @settings[:myfile].should == "/other/file" + @settings[:myfile].should == otherfile @settings.metadata(:myfile).should == {:owner => "suser", :group => "sgroup", :mode => "644"} end it "should support specifying a single piece of metadata (owner, group, or mode) in the configuration file" do @settings.setdefaults :section, :myfile => ["/myfile", "a"] + otherfile = make_absolute("/other/file") text = "[main] - myfile = /other/file {owner = service} + myfile = #{otherfile} {owner = service} " file = "/some/file" @settings.expects(:read_file).returns(text) @settings.parse - @settings[:myfile].should == "/other/file" + @settings[:myfile].should == otherfile @settings.metadata(:myfile).should == {:owner => "suser"} end @@ -601,16 +606,6 @@ describe Puppet::Util::Settings do @settings.reparse end - it "should use a cached LoadedFile instance" do - first = mock 'first' - second = mock 'second' - Puppet::Util::LoadedFile.expects(:new).times(2).with("/test/file").returns(first).then.returns(second) - - @settings.file.should equal(first) - Puppet::Util::Cacher.expire - @settings.file.should equal(second) - end - it "should replace in-memory values with on-file values" do # Init the value text = "[main]\none = disk-init\n" @@ -1104,4 +1099,14 @@ describe Puppet::Util::Settings do it "should cache the result" end + + describe "#writesub" do + it "should only pass valid arguments to File.open" do + settings = Puppet::Util::Settings.new + settings.stubs(:get_config_file_default).with(:privatekeydir).returns(OpenStruct.new(:mode => "750")) + + File.expects(:open).with("/path/to/keydir", "w", 750).returns true + settings.writesub(:privatekeydir, "/path/to/keydir") + end + end end diff --git a/spec/unit/util/storage_spec.rb b/spec/unit/util/storage_spec.rb index 90c11aa69..575ad1ef3 100755 --- a/spec/unit/util/storage_spec.rb +++ b/spec/unit/util/storage_spec.rb @@ -8,7 +8,7 @@ describe Puppet::Util::Storage do include PuppetSpec::Files before(:all) do - @basepath = Puppet.features.posix? ? "/somepath" : "C:/somepath" + @basepath = make_absolute("/somepath") Puppet[:statedir] = tmpdir("statedir") end |
