diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 79fda18ee..c7ac28c00 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,76 +1,107 @@ dir = File.expand_path(File.dirname(__FILE__)) $LOAD_PATH.unshift File.join(dir, 'lib') # Don't want puppet getting the command line arguments for rake or autotest ARGV.clear require 'puppet' require 'mocha' gem 'rspec', '>=2.0.0' require 'rspec/expectations' # So everyone else doesn't have to include this base constant. module PuppetSpec FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR) end require 'pathname' require 'tmpdir' require 'puppet_spec/verbose' require 'puppet_spec/files' require 'puppet_spec/fixtures' require 'puppet_spec/matchers' require 'monkey_patches/alias_should_to_must' require 'monkey_patches/publicize_methods' Pathname.glob("#{dir}/shared_behaviours/**/*.rb") do |behaviour| require behaviour.relative_path_from(Pathname.new(dir)) end RSpec.configure do |config| include PuppetSpec::Fixtures config.mock_with :mocha config.before :each do GC.disable + # We need to preserve the current state of all our indirection cache and + # terminus classes. This is pretty important, because changes to these + # are global and lead to order dependencies in our testing. + # + # We go direct to the implementation because there is no safe, sane public + # API to manage restoration of these to their default values. This + # should, once the value is proved, be moved to a standard API on the + # indirector. + # + # To make things worse, a number of the tests stub parts of the + # indirector. These stubs have very specific expectations that what + # little of the public API we could use is, well, likely to explode + # randomly in some tests. So, direct access. --daniel 2011-08-30 + $saved_indirection_state = {} + indirections = Puppet::Indirector::Indirection.send(:class_variable_get, :@@indirections) + indirections.each do |indirector| + $saved_indirection_state[indirector.name] = { + :@terminus_class => indirector.instance_variable_get(:@terminus_class), + :@cache_glass => indirector.instance_variable_get(:@cache_class) + } + end + # these globals are set by Application $puppet_application_mode = nil $puppet_application_name = nil # REVISIT: I think this conceals other bad tests, but I don't have time to # fully diagnose those right now. When you read this, please come tell me # I suck for letting this float. --daniel 2011-04-21 Signal.stubs(:trap) # Set the confdir and vardir to gibberish so that tests # have to be correctly mocked. Puppet[:confdir] = "/dev/null" Puppet[:vardir] = "/dev/null" # Avoid opening ports to the outside world Puppet.settings[:bindaddress] = "127.0.0.1" @logs = [] Puppet::Util::Log.newdestination(Puppet::Test::LogCollector.new(@logs)) @log_level = Puppet::Util::Log.level end config.after :each do Puppet.settings.clear Puppet::Node::Environment.clear Puppet::Util::Storage.clear Puppet::Util::ExecutionStub.reset PuppetSpec::Files.cleanup @logs.clear Puppet::Util::Log.close_all Puppet::Util::Log.level = @log_level + # Restore the indirector configuration. See before hook. + indirections = Puppet::Indirector::Indirection.send(:class_variable_get, :@@indirections) + indirections.each do |indirector| + $saved_indirection_state.fetch(indirector.name, {}).each do |variable, value| + indirector.instance_variable_set(variable, value) + end + end + $saved_indirection_state = nil + GC.enable end end diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb index 4c6b80137..cb36e58a4 100755 --- a/spec/unit/face/node_spec.rb +++ b/spec/unit/face/node_spec.rb @@ -1,271 +1,271 @@ #!/usr/bin/env rspec require 'spec_helper' require 'puppet/face' describe Puppet::Face[:node, '0.0.1'] do after :all do Puppet::SSL::Host.ca_location = :none end describe '#cleanup' do it "should clean everything" do { "cert" => ['hostname'], "cached_facts" => ['hostname'], "cached_node" => ['hostname'], "reports" => ['hostname'], # Support for cleaning storeconfigs has been temporarily suspended. # "storeconfigs" => ['hostname', :unexport] }.each { |k, v| subject.expects("clean_#{k}".to_sym).with(*v) } subject.cleanup('hostname', :unexport) end end describe 'when running #clean' do before :each do Puppet::Node::Facts.indirection.stubs(:terminus_class=) Puppet::Node::Facts.indirection.stubs(:cache_class=) Puppet::Node.stubs(:terminus_class=) Puppet::Node.stubs(:cache_class=) end it 'should invoke #cleanup' do subject.expects(:cleanup).with('hostname', nil) subject.clean('hostname') end end describe "clean action" do before :each do Puppet::Node::Facts.indirection.stubs(:terminus_class=) Puppet::Node::Facts.indirection.stubs(:cache_class=) Puppet::Node.stubs(:terminus_class=) Puppet::Node.stubs(:cache_class=) subject.stubs(:cleanup) end it "should have a clean action" do subject.should be_action :clean end it "should not accept a call with no arguments" do expect { subject.clean() }.should raise_error end it "should accept a node name" do expect { subject.clean('hostname') }.should_not raise_error end it "should accept more than one node name" do expect do subject.clean('hostname', 'hostname2', {}) end.should_not raise_error expect do subject.clean('hostname', 'hostname2', 'hostname3', { :unexport => true }) end.should_not raise_error end it "should accept the option --unexport" do expect { subject.help('hostname', :unexport => true) }. should_not raise_error ArgumentError end context "clean action" do subject { Puppet::Face[:node, :current] } before :each do Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) end describe "during setup" do it "should set facts terminus and cache class to yaml" do Puppet::Node::Facts.indirection.expects(:terminus_class=).with(:yaml) Puppet::Node::Facts.indirection.expects(:cache_class=).with(:yaml) subject.clean('hostname') end it "should run in master mode" do subject.clean('hostname') $puppet_application_mode.name.should == :master end it "should set node cache as yaml" do Puppet::Node.indirection.expects(:terminus_class=).with(:yaml) Puppet::Node.indirection.expects(:cache_class=).with(:yaml) subject.clean('hostname') end it "should manage the certs if the host is a CA" do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true) Puppet::SSL::Host.expects(:ca_location=).with(:local) subject.clean('hostname') end it "should not manage the certs if the host is not a CA" do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(false) Puppet::SSL::Host.expects(:ca_location=).with(:none) subject.clean('hostname') end end describe "when cleaning certificate" do before :each do Puppet::SSL::Host.stubs(:destroy) @ca = mock() Puppet::SSL::CertificateAuthority.stubs(:instance).returns(@ca) end it "should send the :destroy order to the ca if we are a CA" do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true) @ca.expects(:revoke).with(@host) @ca.expects(:destroy).with(@host) subject.clean_cert(@host) end it "should not destroy the certs if we are not a CA" do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(false) @ca.expects(:revoke).never @ca.expects(:destroy).never subject.clean_cert(@host) end end describe "when cleaning cached facts" do it "should destroy facts" do @host = 'node' Puppet::Node::Facts.indirection.expects(:destroy).with(@host) subject.clean_cached_facts(@host) end end describe "when cleaning cached node" do it "should destroy the cached node" do - Puppet::Node::Yaml.any_instance.expects(:destroy) + Puppet::Node.indirection.expects(:destroy).with(@host) subject.clean_cached_node(@host) end end describe "when cleaning archived reports" do it "should tell the reports to remove themselves" do Puppet::Transaction::Report.indirection.stubs(:destroy).with(@host) subject.clean_reports(@host) end end # describe "when cleaning storeconfigs entries for host", :if => Puppet.features.rails? do # before :each do # # Stub this so we don't need access to the DB # require 'puppet/rails/host' # # Puppet.stubs(:[]).with(:storeconfigs).returns(true) # # Puppet::Rails.stubs(:connect) # @rails_node = stub_everything 'rails_node' # Puppet::Rails::Host.stubs(:find_by_name).returns(@rails_node) # end # # it "should connect to the database" do # Puppet::Rails.expects(:connect) # subject.clean_storeconfigs(@host, false) # end # # it "should find the right host entry" do # Puppet::Rails::Host.expects(:find_by_name).with(@host).returns(@rails_node) # subject.clean_storeconfigs(@host, false) # end # # describe "without unexport" do # it "should remove the host and it's content" do # @rails_node.expects(:destroy) # subject.clean_storeconfigs(@host, false) # end # end # # describe "with unexport" do # before :each do # @rails_node.stubs(:id).returns(1234) # # @type = stub_everything 'type' # @type.stubs(:validattr?).with(:ensure).returns(true) # # @ensure_name = stub_everything 'ensure_name', :id => 23453 # Puppet::Rails::ParamName.stubs(:find_or_create_by_name).returns(@ensure_name) # # @param_values = stub_everything 'param_values' # @resource = stub_everything 'resource', :param_values => @param_values, :restype => "File" # Puppet::Rails::Resource.stubs(:find).returns([@resource]) # end # # it "should find all resources" do # Puppet::Rails::Resource.expects(:find).with(:all, {:include => {:param_values => :param_name}, :conditions => ["exported=? AND host_id=?", true, 1234]}).returns([]) # # subject.clean_storeconfigs(@host, true) # end # # describe "with an exported native type" do # before :each do # Puppet::Type.stubs(:type).returns(@type) # @type.expects(:validattr?).with(:ensure).returns(true) # end # # it "should test a native type for ensure as an attribute" do # subject.clean_storeconfigs(@host, true) # end # # it "should delete the old ensure parameter" do # ensure_param = stub 'ensure_param', :id => 12345, :line => 12 # @param_values.stubs(:find).returns(ensure_param) # Puppet::Rails::ParamValue.expects(:delete).with(12345); # subject.clean_storeconfigs(@host, true) # end # # it "should add an ensure => absent parameter" do # @param_values.expects(:create).with(:value => "absent", # :line => 0, # :param_name => @ensure_name) # subject.clean_storeconfigs(@host, true) # end # end # # describe "with an exported definition" do # it "should try to lookup a definition and test it for the ensure argument" do # Puppet::Type.stubs(:type).returns(nil) # definition = stub_everything 'definition', :arguments => { 'ensure' => 'present' } # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition) # subject.clean_storeconfigs(@host, true) # end # end # # it "should not unexport the resource of an unknown type" do # Puppet::Type.stubs(:type).returns(nil) # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil) # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never # subject.clean_storeconfigs(@host) # end # # it "should not unexport the resource of a not ensurable native type" do # Puppet::Type.stubs(:type).returns(@type) # @type.expects(:validattr?).with(:ensure).returns(false) # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil) # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never # subject.clean_storeconfigs(@host, true) # end # # it "should not unexport the resource of a not ensurable definition" do # Puppet::Type.stubs(:type).returns(nil) # definition = stub_everything 'definition', :arguments => { 'foobar' => 'someValue' } # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition) # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never # subject.clean_storeconfigs(@host, true) # end # end # end end end end