diff --git a/autotest/puppet_rspec.rb b/autotest/puppet_rspec.rb index bfc1a6a43..5ff794e9d 100644 --- a/autotest/puppet_rspec.rb +++ b/autotest/puppet_rspec.rb @@ -1,60 +1,60 @@ require 'autotest' require 'autotest/rspec' Autotest.add_hook :initialize do |at| at.clear_mappings # the libraries under lib/puppet at.add_mapping(%r%^lib/puppet/(.*)\.rb$%) { |filename, m| at.files_matching %r!spec/(unit|integration)/#{m[1]}.rb! } # the actual spec files themselves at.add_mapping(%r%^spec/(unit|integration)/.*\.rb$%) { |filename, _| filename } # force a complete re-run for all of these: # main puppet lib at.add_mapping(%r!^lib/puppet\.rb$!) { |filename, _| at.files_matching %r!spec/(unit|integration)/.*\.rb! } # the spec_helper at.add_mapping(%r!^spec/spec_helper\.rb$!) { |filename, _| at.files_matching %r!spec/(unit|integration)/.*\.rb! } # the puppet test libraries at.add_mapping(%r!^test/lib/puppettest/.*!) { |filename, _| at.files_matching %r!spec/(unit|integration)/.*\.rb! } # the puppet spec libraries at.add_mapping(%r!^spec/lib/spec.*!) { |filename, _| at.files_matching %r!spec/(unit|integration)/.*\.rb! } # the monkey patches for rspec at.add_mapping(%r!^spec/lib/monkey_patches/.*!) { |filename, _| at.files_matching %r!spec/(unit|integration)/.*\.rb! } end class Autotest::PuppetRspec < Autotest::Rspec # Autotest will look for spec commands in the following # locations, in this order: # # * bin/spec # * default spec bin/loader installed in Rubygems # * our local vendor/gems/rspec/bin/spec def spec_commands [ + File.join('vendor', 'gems', 'rspec', 'bin', 'spec') , File.join('bin', 'spec'), - File.join(Config::CONFIG['bindir'], 'spec'), - File.join('vendor', 'gems', 'rspec', 'bin', 'spec') + File.join(Config::CONFIG['bindir'], 'spec') ] end end diff --git a/spec/unit/file_serving/configuration.rb b/spec/unit/file_serving/configuration.rb index df46b9b6a..eecaefe5f 100755 --- a/spec/unit/file_serving/configuration.rb +++ b/spec/unit/file_serving/configuration.rb @@ -1,227 +1,224 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/file_serving/configuration' -module FSConfigurationTesting - def setup - @path = "/path/to/configuration/file.conf" - Puppet.settings.stubs(:value).with(:fileserverconfig).returns(@path) - end - - def teardown - Puppet::FileServing::Configuration.clear_cache - end -end - 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::FileServing::Configuration.clear_cache Puppet::FileServing::Configuration.create.should_not equal(old) end after do Puppet::FileServing::Configuration.clear_cache end end -describe Puppet::FileServing::Configuration, " when initializing" do - include FSConfigurationTesting - - it "should work without a configuration file" do - FileTest.stubs(:exists?).with(@path).returns(false) - proc { Puppet::FileServing::Configuration.create }.should_not raise_error - end - - it "should parse the configuration file if present" do - FileTest.stubs(:exists?).with(@path).returns(true) - @parser = mock 'parser' - @parser.expects(:parse).returns({}) - Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) - Puppet::FileServing::Configuration.create - end - - it "should determine the path to the configuration file from the Puppet settings" do - Puppet::FileServing::Configuration.create - end -end - -describe Puppet::FileServing::Configuration, " when parsing the configuration file" do - include FSConfigurationTesting - - before do - FileTest.stubs(:exists?).with(@path).returns(true) - @parser = mock 'parser' - Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) - end - - 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.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 - 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.mounted?("one").should be_true - # Now parse again - @parser.expects(:parse).returns("two" => mock('other')) - config.send(:readconfig, false) - config.mounted?("one").should be_false - config.mounted?("two").should be_true - end - - 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 - # Now parse again, so the exception gets thrown - config.send(:readconfig, false) - config.mounted?("one").should be_true - end -end - -describe Puppet::FileServing::Configuration, " when finding files" do - include FSConfigurationTesting - - before do - @parser = mock 'parser' - @parser.stubs(:changed?).returns true - FileTest.stubs(:exists?).with(@path).returns(true) - Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) - - @mount1 = stub 'mount', :name => "one" - @mounts = {"one" => @mount1} - - Facter.stubs(:value).with("hostname").returns("whatever") - - @config = Puppet::FileServing::Configuration.create - end - - it "should fail if the uri does not match a leading slash followed by a valid mount name" do - @parser.expects(:parse).returns(@mounts) - proc { @config.file_path("something") }.should raise_error(ArgumentError) - end - - it "should use the first term after the first slash for the mount name" do - @parser.expects(:parse).returns(@mounts) - FileTest.stubs(:exists?).returns(true) - @mount1.expects(:file) - @config.file_path("/one") - end - - it "should use the remainder of the URI after the mount name as the file name" do - @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file).with("something/else", {}) - FileTest.stubs(:exists?).returns(true) - @config.file_path("/one/something/else") - end - - it "should treat a bare name as a mount and no relative file" do - @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file).with(nil, {}) - FileTest.stubs(:exists?).returns(true) - @config.file_path("/one") - end - - it "should treat a name with a trailing slash equivalently to a name with no trailing slash" do - @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file).with(nil, {}) - FileTest.stubs(:exists?).returns(true) - @config.file_path("/one/") - end - - it "should return nil if the mount cannot be found" do - @parser.expects(:changed?).returns(true) - @parser.expects(:parse).returns({}) - @config.file_path("/one/something").should be_nil - end - - it "should return nil if the mount does not contain the file" do - @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file).with("something/else", {}).returns(nil) - @config.file_path("/one/something/else").should be_nil - end - - it "should return the fully qualified path if the mount exists" do - @parser.expects(:parse).returns(@mounts) - @mount1.expects(:file).with("something/else", {}).returns("/full/path") - @config.file_path("/one/something/else").should == "/full/path" - end - - it "should reparse the configuration file when it has changed" do - @mount1.stubs(:file).returns("whatever") - @parser.expects(:changed?).returns(true) - @parser.expects(:parse).returns(@mounts) - FileTest.stubs(:exists?).returns(true) - @config.file_path("/one/something") - - @parser.expects(:changed?).returns(true) - @parser.expects(:parse).returns({}) - @config.file_path("/one/something").should be_nil - end -end - -describe Puppet::FileServing::Configuration, " when checking authorization" do - include FSConfigurationTesting - - before do - @parser = mock 'parser' - @parser.stubs(:changed?).returns true - FileTest.stubs(:exists?).with(@path).returns(true) - Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) - - @mount1 = stub 'mount', :name => "one" - @mounts = {"one" => @mount1} - @parser.stubs(:parse).returns(@mounts) - - Facter.stubs(:value).with("hostname").returns("whatever") - - @config = Puppet::FileServing::Configuration.create - end - - it "should return false if the mount cannot be found" do - @config.authorized?("/nope/my/file").should be_false - end - - it "should use the mount to determine authorization" do - @mount1.expects(:allowed?) - @config.authorized?("/one/my/file") - end - - it "should pass the client's name to the mount if provided" do - @mount1.expects(:allowed?).with("myhost", nil) - @config.authorized?("/one/my/file", :node => "myhost") - end +describe Puppet::FileServing::Configuration do - it "should pass the client's IP to the mount if provided" do - @mount1.expects(:allowed?).with("myhost", "myip") - @config.authorized?("/one/my/file", :node => "myhost", :ipaddress => "myip") + before :each do + @path = "/path/to/configuration/file.conf" + Puppet.settings.stubs(:value).with(:fileserverconfig).returns(@path) end - it "should return true if the mount allows the client" do - @mount1.expects(:allowed?).returns(true) - @config.authorized?("/one/my/file").should be_true + after :each do + Puppet::FileServing::Configuration.clear_cache end - it "should return false if the mount denies the client" do - @mount1.expects(:allowed?).returns(false) - @config.authorized?("/one/my/file").should be_false - end -end + describe Puppet::FileServing::Configuration, " 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 + end + + it "should parse the configuration file if present" do + FileTest.stubs(:exists?).with(@path).returns(true) + @parser = mock 'parser' + @parser.expects(:parse).returns({}) + Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) + Puppet::FileServing::Configuration.create + end + + it "should determine the path to the configuration file from the Puppet settings" do + Puppet::FileServing::Configuration.create + end + end + + describe Puppet::FileServing::Configuration, " when parsing the configuration file" do + + before do + FileTest.stubs(:exists?).with(@path).returns(true) + @parser = mock 'parser' + Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) + end + + 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.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 + 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.mounted?("one").should be_true + # Now parse again + @parser.expects(:parse).returns("two" => mock('other')) + config.send(:readconfig, false) + config.mounted?("one").should be_false + config.mounted?("two").should be_true + end + + 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 + # Now parse again, so the exception gets thrown + config.send(:readconfig, false) + config.mounted?("one").should be_true + end + end + + describe Puppet::FileServing::Configuration, " when finding files" do + + before do + @parser = mock 'parser' + @parser.stubs(:changed?).returns true + FileTest.stubs(:exists?).with(@path).returns(true) + Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) + + @mount1 = stub 'mount', :name => "one" + @mounts = {"one" => @mount1} + + Facter.stubs(:value).with("hostname").returns("whatever") + + @config = Puppet::FileServing::Configuration.create + end + + it "should fail if the uri does not match a leading slash followed by a valid mount name" do + @parser.expects(:parse).returns(@mounts) + proc { @config.file_path("something") }.should raise_error(ArgumentError) + end + + it "should use the first term after the first slash for the mount name" do + @parser.expects(:parse).returns(@mounts) + FileTest.stubs(:exists?).returns(true) + @mount1.expects(:file) + @config.file_path("/one") + end + + it "should use the remainder of the URI after the mount name as the file name" do + @parser.expects(:parse).returns(@mounts) + @mount1.expects(:file).with("something/else", {}) + FileTest.stubs(:exists?).returns(true) + @config.file_path("/one/something/else") + end + + it "should treat a bare name as a mount and no relative file" do + @parser.expects(:parse).returns(@mounts) + @mount1.expects(:file).with(nil, {}) + FileTest.stubs(:exists?).returns(true) + @config.file_path("/one") + end + + it "should treat a name with a trailing slash equivalently to a name with no trailing slash" do + @parser.expects(:parse).returns(@mounts) + @mount1.expects(:file).with(nil, {}) + FileTest.stubs(:exists?).returns(true) + @config.file_path("/one/") + end + + it "should return nil if the mount cannot be found" do + @parser.expects(:changed?).returns(true) + @parser.expects(:parse).returns({}) + @config.file_path("/one/something").should be_nil + end + + it "should return nil if the mount does not contain the file" do + @parser.expects(:parse).returns(@mounts) + @mount1.expects(:file).with("something/else", {}).returns(nil) + @config.file_path("/one/something/else").should be_nil + end + + it "should return the fully qualified path if the mount exists" do + @parser.expects(:parse).returns(@mounts) + @mount1.expects(:file).with("something/else", {}).returns("/full/path") + @config.file_path("/one/something/else").should == "/full/path" + end + + it "should reparse the configuration file when it has changed" do + @mount1.stubs(:file).returns("whatever") + @parser.expects(:changed?).returns(true) + @parser.expects(:parse).returns(@mounts) + FileTest.stubs(:exists?).returns(true) + @config.file_path("/one/something") + + @parser.expects(:changed?).returns(true) + @parser.expects(:parse).returns({}) + @config.file_path("/one/something").should be_nil + end + end + + describe Puppet::FileServing::Configuration, " when checking authorization" do + + before do + @parser = mock 'parser' + @parser.stubs(:changed?).returns true + FileTest.stubs(:exists?).with(@path).returns(true) + Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser) + + @mount1 = stub 'mount', :name => "one" + @mounts = {"one" => @mount1} + @parser.stubs(:parse).returns(@mounts) + + Facter.stubs(:value).with("hostname").returns("whatever") + + @config = Puppet::FileServing::Configuration.create + end + + it "should return false if the mount cannot be found" do + @config.authorized?("/nope/my/file").should be_false + end + + it "should use the mount to determine authorization" do + @mount1.expects(:allowed?) + @config.authorized?("/one/my/file") + end + + it "should pass the client's name to the mount if provided" do + @mount1.expects(:allowed?).with("myhost", nil) + @config.authorized?("/one/my/file", :node => "myhost") + end + + it "should pass the client's IP to the mount if provided" do + @mount1.expects(:allowed?).with("myhost", "myip") + @config.authorized?("/one/my/file", :node => "myhost", :ipaddress => "myip") + end + + it "should return true if the mount allows the client" do + @mount1.expects(:allowed?).returns(true) + @config.authorized?("/one/my/file").should be_true + end + + it "should return false if the mount denies the client" do + @mount1.expects(:allowed?).returns(false) + @config.authorized?("/one/my/file").should be_false + end + end +end \ No newline at end of file diff --git a/spec/unit/file_serving/configuration/parser.rb b/spec/unit/file_serving/configuration/parser.rb index aa296cf43..df2f629d5 100755 --- a/spec/unit/file_serving/configuration/parser.rb +++ b/spec/unit/file_serving/configuration/parser.rb @@ -1,132 +1,135 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/file_serving/configuration/parser' describe Puppet::FileServing::Configuration::Parser do it "should subclass the LoadedFile class" do Puppet::FileServing::Configuration::Parser.superclass.should equal(Puppet::Util::LoadedFile) end end + module FSConfigurationParserTesting - def setup + def mock_file_content(content) + # We want an array, but we actually want our carriage returns on all of it. + lines = content.split("\n").collect { |l| l + "\n" } + @filehandle.stubs(:each).multiple_yields(*lines) + end +end + +describe Puppet::FileServing::Configuration::Parser do + before :each do @path = "/my/config.conf" FileTest.stubs(:exists?).with(@path).returns(true) FileTest.stubs(:readable?).with(@path).returns(true) @filehandle = mock 'filehandle' File.expects(:open).with(@path).yields(@filehandle) @parser = Puppet::FileServing::Configuration::Parser.new(@path) end - def mock_file_content(content) - # We want an array, but we actually want our carriage returns on all of it. - lines = content.split("\n").collect { |l| l + "\n" } - @filehandle.stubs(:each).multiple_yields(*lines) - end -end - -describe Puppet::FileServing::Configuration::Parser, " when parsing" do - include FSConfigurationParserTesting + describe Puppet::FileServing::Configuration::Parser, " when parsing" do + include FSConfigurationParserTesting - before do - @parser.stubs(:add_modules_mount) - end + before do + @parser.stubs(:add_modules_mount) + end - it "should allow comments" do - @filehandle.expects(:each).yields("# this is a comment\n") - proc { @parser.parse }.should_not raise_error - end + it "should allow comments" do + @filehandle.expects(:each).yields("# this is a comment\n") + proc { @parser.parse }.should_not raise_error + end - it "should allow blank lines" do - @filehandle.expects(:each).yields("\n") - proc { @parser.parse }.should_not raise_error - end + it "should allow blank lines" do + @filehandle.expects(:each).yields("\n") + proc { @parser.parse }.should_not raise_error + end - it "should create a new mount for each section in the configuration" do - mount1 = mock 'one' - mount2 = mock 'two' - Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) - Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) - mock_file_content "[one]\n[two]\n" - @parser.parse - end + it "should create a new mount for each section in the configuration" do + mount1 = mock 'one' + mount2 = mock 'two' + Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) + Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) + mock_file_content "[one]\n[two]\n" + @parser.parse + end - # This test is almost the exact same as the previous one. - it "should return a hash of the created mounts" do - mount1 = mock 'one' - mount2 = mock 'two' - Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) - Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) - mock_file_content "[one]\n[two]\n" + # This test is almost the exact same as the previous one. + it "should return a hash of the created mounts" do + mount1 = mock 'one' + mount2 = mock 'two' + Puppet::FileServing::Mount.expects(:new).with("one").returns(mount1) + Puppet::FileServing::Mount.expects(:new).with("two").returns(mount2) + mock_file_content "[one]\n[two]\n" - @parser.parse.should == {"one" => mount1, "two" => mount2} - end + @parser.parse.should == {"one" => mount1, "two" => mount2} + end - it "should only allow mount names that are alphanumeric plus dashes" do - mock_file_content "[a*b]\n" - proc { @parser.parse }.should raise_error(ArgumentError) - end + it "should only allow mount names that are alphanumeric plus dashes" do + mock_file_content "[a*b]\n" + proc { @parser.parse }.should raise_error(ArgumentError) + end - it "should fail if the value for path/allow/deny starts with an equals sign" do - mock_file_content "[one]\npath = /testing" - proc { @parser.parse }.should raise_error(ArgumentError) + it "should fail if the value for path/allow/deny starts with an equals sign" do + mock_file_content "[one]\npath = /testing" + proc { @parser.parse }.should raise_error(ArgumentError) + end end -end -describe Puppet::FileServing::Configuration::Parser, " when parsing mount attributes" do - include FSConfigurationParserTesting + describe Puppet::FileServing::Configuration::Parser, " when parsing mount attributes" do + include FSConfigurationParserTesting - before do - @mount = stub 'mount', :name => "one" - Puppet::FileServing::Mount.expects(:new).with("one").returns(@mount) - @parser.stubs(:add_modules_mount) - end + before do + @mount = stub 'mount', :name => "one" + Puppet::FileServing::Mount.expects(:new).with("one").returns(@mount) + @parser.stubs(:add_modules_mount) + end - it "should set the mount path to the path attribute from that section" do - mock_file_content "[one]\npath /some/path\n" + it "should set the mount path to the path attribute from that section" do + mock_file_content "[one]\npath /some/path\n" - @mount.expects(:path=).with("/some/path") - @parser.parse - end + @mount.expects(:path=).with("/some/path") + @parser.parse + end - it "should tell the mount to allow any allow values from the section" do - mock_file_content "[one]\nallow something\n" + it "should tell the mount to allow any allow values from the section" do + mock_file_content "[one]\nallow something\n" - @mount.expects(:info) - @mount.expects(:allow).with("something") - @parser.parse - end + @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" + it "should tell the mount to deny any deny values from the section" do + mock_file_content "[one]\ndeny something\n" - @mount.expects(:info) - @mount.expects(:deny).with("something") - @parser.parse - end + @mount.expects(:info) + @mount.expects(:deny).with("something") + @parser.parse + end - it "should fail on any attributes other than path, allow, and deny" do - mock_file_content "[one]\ndo something\n" + it "should fail on any attributes other than path, allow, and deny" do + mock_file_content "[one]\ndo something\n" - proc { @parser.parse }.should raise_error(ArgumentError) + proc { @parser.parse }.should raise_error(ArgumentError) + end end -end -describe Puppet::FileServing::Configuration::Parser, " when parsing the modules mount" do - include FSConfigurationParserTesting + describe Puppet::FileServing::Configuration::Parser, " when parsing the modules mount" do + include FSConfigurationParserTesting - before do - @mount = stub 'mount', :name => "modules" - Puppet::FileServing::Mount.expects(:new).with("modules").returns(@mount) - end + before do + @mount = stub 'mount', :name => "modules" + Puppet::FileServing::Mount.expects(:new).with("modules").returns(@mount) + end - it "should warn if a path is set" do - mock_file_content "[modules]\npath /some/path\n" + it "should warn if a path is set" do + mock_file_content "[modules]\npath /some/path\n" - @modules.expects(:path=).never - Puppet.expects(:warning) - @parser.parse + @modules.expects(:path=).never + Puppet.expects(:warning) + @parser.parse + end end -end +end \ No newline at end of file diff --git a/spec/unit/indirector/checksum/file.rb b/spec/unit/indirector/checksum/file.rb index 82319fa40..4f8ee98b2 100755 --- a/spec/unit/indirector/checksum/file.rb +++ b/spec/unit/indirector/checksum/file.rb @@ -1,142 +1,140 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-22. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/checksum/file' -module FileChecksumTesting - def setup - Puppet.settings.stubs(:use) - @store = Puppet::Checksum::File.new - - @value = "70924d6fa4b2d745185fa4660703a5c0" - @sum = stub 'sum', :name => @value - - @dir = "/what/ever" - - Puppet.stubs(:[]).with(:bucketdir).returns(@dir) - - @path = @store.path(@value) - end -end - describe Puppet::Checksum::File do it "should be a subclass of the File terminus class" do Puppet::Checksum::File.superclass.should equal(Puppet::Indirector::File) end it "should have documentation" do Puppet::Checksum::File.doc.should be_instance_of(String) end end describe Puppet::Checksum::File, " when initializing" do it "should use the filebucket settings section" do Puppet.settings.expects(:use).with(:filebucket) Puppet::Checksum::File.new end end -describe Puppet::Checksum::File, " when determining file paths" do - include FileChecksumTesting - # I was previously passing the object in. - it "should use the value passed in to path() as the checksum" do - @value.expects(:name).never - @store.path(@value) - end +describe Puppet::Checksum::File do + before :each do + Puppet.settings.stubs(:use) + @store = Puppet::Checksum::File.new - it "should use the value of the :bucketdir setting as the root directory" do - @path.should =~ %r{^#{@dir}} - end + @value = "70924d6fa4b2d745185fa4660703a5c0" + @sum = stub 'sum', :name => @value - it "should choose a path 8 directories deep with each directory name being the respective character in the checksum" do - dirs = @value[0..7].split("").join(File::SEPARATOR) - @path.should be_include(dirs) - end + @dir = "/what/ever" - it "should use the full checksum as the final directory name" do - File.basename(File.dirname(@path)).should == @value - end + Puppet.stubs(:[]).with(:bucketdir).returns(@dir) - it "should use 'contents' as the actual file name" do - File.basename(@path).should == "contents" + @path = @store.path(@value) end - it "should use the bucketdir, the 8 sum character directories, the full checksum, and 'contents' as the full file name" do - @path.should == [@dir, @value[0..7].split(""), @value, "contents"].flatten.join(File::SEPARATOR) - end -end -describe Puppet::Checksum::File, " when retrieving files" do - include FileChecksumTesting + describe Puppet::Checksum::File, " when determining file paths" do - # The smallest test that will use the calculated path - it "should look for the calculated path" do - File.expects(:exist?).with(@path).returns(false) - @store.find(@value) - end + # I was previously passing the object in. + it "should use the value passed in to path() as the checksum" do + @value.expects(:name).never + @store.path(@value) + end - it "should return an instance of Puppet::Checksum created with the content if the file exists" do - content = "my content" - sum = stub 'file' - Puppet::Checksum.expects(:new).with(content).returns(sum) + it "should use the value of the :bucketdir setting as the root directory" do + @path.should =~ %r{^#{@dir}} + end - File.expects(:exist?).with(@path).returns(true) - File.expects(:read).with(@path).returns(content) + it "should choose a path 8 directories deep with each directory name being the respective character in the checksum" do + dirs = @value[0..7].split("").join(File::SEPARATOR) + @path.should be_include(dirs) + end - @store.find(@value).should equal(sum) - end + it "should use the full checksum as the final directory name" do + File.basename(File.dirname(@path)).should == @value + end - it "should return nil if no file is found" do - File.expects(:exist?).with(@path).returns(false) - @store.find(@value).should be_nil - end + it "should use 'contents' as the actual file name" do + File.basename(@path).should == "contents" + end - it "should fail intelligently if a found file cannot be read" do - File.expects(:exist?).with(@path).returns(true) - File.expects(:read).with(@path).raises(RuntimeError) - proc { @store.find(@value) }.should raise_error(Puppet::Error) + it "should use the bucketdir, the 8 sum character directories, the full checksum, and 'contents' as the full file name" do + @path.should == [@dir, @value[0..7].split(""), @value, "contents"].flatten.join(File::SEPARATOR) + end end -end -describe Puppet::Checksum::File, " when saving files" do - include FileChecksumTesting + describe Puppet::Checksum::File, " when retrieving files" do + + # The smallest test that will use the calculated path + it "should look for the calculated path" do + File.expects(:exist?).with(@path).returns(false) + @store.find(@value) + end + + it "should return an instance of Puppet::Checksum created with the content if the file exists" do + content = "my content" + sum = stub 'file' + Puppet::Checksum.expects(:new).with(content).returns(sum) + + File.expects(:exist?).with(@path).returns(true) + File.expects(:read).with(@path).returns(content) - # LAK:FIXME I don't know how to include in the spec the fact that we're - # using the superclass's save() method and thus are acquiring all of - # it's behaviours. - it "should save the content to the calculated path" do - File.stubs(:directory?).with(File.dirname(@path)).returns(true) - File.expects(:open).with(@path, "w") + @store.find(@value).should equal(sum) + end - file = stub 'file', :name => @value - @store.save(file) + it "should return nil if no file is found" do + File.expects(:exist?).with(@path).returns(false) + @store.find(@value).should be_nil + end + + it "should fail intelligently if a found file cannot be read" do + File.expects(:exist?).with(@path).returns(true) + File.expects(:read).with(@path).raises(RuntimeError) + proc { @store.find(@value) }.should raise_error(Puppet::Error) + end end - it "should make any directories necessary for storage" do - FileUtils.expects(:mkdir_p).with do |arg| - File.umask == 0007 and arg == File.dirname(@path) + describe Puppet::Checksum::File, " when saving files" do + + # LAK:FIXME I don't know how to include in the spec the fact that we're + # using the superclass's save() method and thus are acquiring all of + # it's behaviours. + it "should save the content to the calculated path" do + File.stubs(:directory?).with(File.dirname(@path)).returns(true) + File.expects(:open).with(@path, "w") + + file = stub 'file', :name => @value + @store.save(file) end - File.expects(:directory?).with(File.dirname(@path)).returns(true) - File.expects(:open).with(@path, "w") - file = stub 'file', :name => @value - @store.save(file) + it "should make any directories necessary for storage" do + FileUtils.expects(:mkdir_p).with do |arg| + File.umask == 0007 and arg == File.dirname(@path) + end + File.expects(:directory?).with(File.dirname(@path)).returns(true) + File.expects(:open).with(@path, "w") + + file = stub 'file', :name => @value + @store.save(file) + end end -end -describe Puppet::Checksum::File, " when deleting files" do - include FileChecksumTesting + describe Puppet::Checksum::File, " when deleting files" do - it "should remove the file at the calculated path" do - File.expects(:exist?).with(@path).returns(true) - File.expects(:unlink).with(@path) + it "should remove the file at the calculated path" do + File.expects(:exist?).with(@path).returns(true) + File.expects(:unlink).with(@path) - file = stub 'file', :name => @value - @store.destroy(file) + file = stub 'file', :name => @value + @store.destroy(file) + end end -end +end \ No newline at end of file diff --git a/spec/unit/indirector/direct_file_server.rb b/spec/unit/indirector/direct_file_server.rb index 2a8ec1a49..9f3652536 100755 --- a/spec/unit/indirector/direct_file_server.rb +++ b/spec/unit/indirector/direct_file_server.rb @@ -1,95 +1,92 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-10-24. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/direct_file_server' -module DirectFileServerTerminusTesting - def setup +describe Puppet::Indirector::DirectFileServer do + before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @direct_file_class = Class.new(Puppet::Indirector::DirectFileServer) do def self.to_s "Testing::Mytype" end end @server = @direct_file_class.new @uri = "file:///my/local" end -end -describe Puppet::Indirector::DirectFileServer, "when finding a single file" do - include DirectFileServerTerminusTesting + describe Puppet::Indirector::DirectFileServer, "when finding a single file" do - it "should return nil if the file does not exist" do - FileTest.expects(:exists?).with("/my/local").returns false - @server.find(@uri).should be_nil - end + it "should return nil if the file does not exist" do + FileTest.expects(:exists?).with("/my/local").returns false + @server.find(@uri).should be_nil + end - it "should return a Content instance created with the full path to the file if the file exists" do - FileTest.expects(:exists?).with("/my/local").returns true - @model.expects(:new).returns(:mycontent) - @server.find(@uri).should == :mycontent + it "should return a Content instance created with the full path to the file if the file exists" do + FileTest.expects(:exists?).with("/my/local").returns true + @model.expects(:new).returns(:mycontent) + @server.find(@uri).should == :mycontent + end end -end -describe Puppet::Indirector::DirectFileServer, "when creating the instance for a single found file" do - include DirectFileServerTerminusTesting + describe Puppet::Indirector::DirectFileServer, "when creating the instance for a single found file" do - before do - @data = mock 'content' - @data.stubs(:collect_attributes) - FileTest.expects(:exists?).with("/my/local").returns true - end + before do + @data = mock 'content' + @data.stubs(:collect_attributes) + FileTest.expects(:exists?).with("/my/local").returns true + end - it "should create the Content instance with the original key as the key" do - @model.expects(:new).with { |key, options| key == @uri }.returns(@data) - @server.find(@uri) - end + it "should create the Content instance with the original key as the key" do + @model.expects(:new).with { |key, options| key == @uri }.returns(@data) + @server.find(@uri) + end - it "should pass the full path to the instance" do - @model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data) - @server.find(@uri) - end + it "should pass the full path to the instance" do + @model.expects(:new).with { |key, options| options[:path] == "/my/local" }.returns(@data) + @server.find(@uri) + end - it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do - @model.expects(:new).returns(@data) - @data.expects(:links=).with(:manage) - @server.find(@uri, :links => :manage) + it "should pass the :links setting on to the created Content instance if the file exists and there is a value for :links" do + @model.expects(:new).returns(@data) + @data.expects(:links=).with(:manage) + @server.find(@uri, :links => :manage) + end end -end -describe Puppet::Indirector::DirectFileServer, "when searching for multiple files" do - include DirectFileServerTerminusTesting + describe Puppet::Indirector::DirectFileServer, "when searching for multiple files" do - it "should return nil if the file does not exist" do - FileTest.expects(:exists?).with("/my/local").returns false - @server.find(@uri).should be_nil - end + it "should return nil if the file does not exist" do + FileTest.expects(:exists?).with("/my/local").returns false + @server.find(@uri).should be_nil + end - it "should pass the original key to :path2instances" do - FileTest.expects(:exists?).with("/my/local").returns true - @server.expects(:path2instances).with { |uri, path, options| uri == @uri } - @server.search(@uri) - end + it "should pass the original key to :path2instances" do + FileTest.expects(:exists?).with("/my/local").returns true + @server.expects(:path2instances).with { |uri, path, options| uri == @uri } + @server.search(@uri) + end - it "should use :path2instances from the terminus_helper to return instances if the file exists" do - FileTest.expects(:exists?).with("/my/local").returns true - @server.expects(:path2instances) - @server.search(@uri) - end + it "should use :path2instances from the terminus_helper to return instances if the file exists" do + FileTest.expects(:exists?).with("/my/local").returns true + @server.expects(:path2instances) + @server.search(@uri) + end - it "should pass any options on to :path2instances" do - FileTest.expects(:exists?).with("/my/local").returns true - @server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}} - @server.search(@uri, :testing => :one, :other => :two) + it "should pass any options on to :path2instances" do + FileTest.expects(:exists?).with("/my/local").returns true + @server.expects(:path2instances).with { |uri, path, options| options == {:testing => :one, :other => :two}} + @server.search(@uri, :testing => :one, :other => :two) + end end -end +end \ No newline at end of file diff --git a/spec/unit/indirector/facts/facter.rb b/spec/unit/indirector/facts/facter.rb index 1fad4c859..0974a60ec 100755 --- a/spec/unit/indirector/facts/facter.rb +++ b/spec/unit/indirector/facts/facter.rb @@ -1,79 +1,76 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-23. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/facts/facter' describe Puppet::Node::Facts::Facter do it "should be a subclass of the Code terminus" do Puppet::Node::Facts::Facter.superclass.should equal(Puppet::Indirector::Code) end it "should have documentation" do Puppet::Node::Facts::Facter.doc.should_not be_nil end it "should be registered with the configuration store indirection" do indirection = Puppet::Indirector::Indirection.instance(:facts) Puppet::Node::Facts::Facter.indirection.should equal(indirection) end it "should have its name set to :facter" do Puppet::Node::Facts::Facter.name.should == :facter end it "should load facts on initialization" do Puppet::Node::Facts::Facter.expects(:loadfacts) Puppet::Node::Facts::Facter.new end end -module TestingCodeFacts - def setup +describe Puppet::Node::Facts::Facter do + before :each do @facter = Puppet::Node::Facts::Facter.new Facter.stubs(:to_hash).returns({}) @name = "me" @facts = @facter.find(@name) end -end -describe Puppet::Node::Facts::Facter, " when finding facts" do - include TestingCodeFacts + describe Puppet::Node::Facts::Facter, " when finding facts" do - it "should return a Facts instance" do - @facts.should be_instance_of(Puppet::Node::Facts) - end + it "should return a Facts instance" do + @facts.should be_instance_of(Puppet::Node::Facts) + end - it "should return a Facts instance with the provided key as the name" do - @facts.name.should == @name - end + it "should return a Facts instance with the provided key as the name" do + @facts.name.should == @name + end - it "should return the Facter facts as the values in the Facts instance" do - Facter.expects(:to_hash).returns("one" => "two") - facts = @facter.find(@name) - facts.values["one"].should == "two" + it "should return the Facter facts as the values in the Facts instance" do + Facter.expects(:to_hash).returns("one" => "two") + facts = @facter.find(@name) + facts.values["one"].should == "two" + end end -end -describe Puppet::Node::Facts::Facter, " when saving facts" do - include TestingCodeFacts + describe Puppet::Node::Facts::Facter, " when saving facts" do - it "should fail" do - proc { @facter.save(@facts) }.should raise_error(Puppet::DevError) + it "should fail" do + proc { @facter.save(@facts) }.should raise_error(Puppet::DevError) + end end -end -describe Puppet::Node::Facts::Facter, " when destroying facts" do - include TestingCodeFacts + describe Puppet::Node::Facts::Facter, " when destroying facts" do - it "should fail" do - proc { @facter.destroy(@facts) }.should raise_error(Puppet::DevError) + it "should fail" do + proc { @facter.destroy(@facts) }.should raise_error(Puppet::DevError) + end end -end -describe Puppet::Node::Facts::Facter, " when loading facts from the factpath" do - it "should load every fact in each factpath directory" -end + describe Puppet::Node::Facts::Facter, " when loading facts from the factpath" do + it "should load every fact in each factpath directory" + end +end \ No newline at end of file diff --git a/spec/unit/indirector/file.rb b/spec/unit/indirector/file.rb index 216c9bfe1..37740f0d0 100755 --- a/spec/unit/indirector/file.rb +++ b/spec/unit/indirector/file.rb @@ -1,160 +1,158 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/file' -module FileTerminusTesting - def setup + +describe Puppet::Indirector::File do + before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @file_class = Class.new(Puppet::Indirector::File) do def self.to_s "Testing::Mytype" end end @searcher = @file_class.new @path = "/my/file" @dir = "/my" end -end + + describe Puppet::Indirector::File, " when finding files" do -describe Puppet::Indirector::File, " when finding files" do - include FileTerminusTesting + it "should provide a method to return file contents at a specified path" do + @searcher.should respond_to(:find) + end - it "should provide a method to return file contents at a specified path" do - @searcher.should respond_to(:find) - end + it "should return file contents as an instance of the model" do + content = "my content" - it "should return file contents as an instance of the model" do - content = "my content" + file = mock 'file' + @model.expects(:new).with(content).returns(file) - file = mock 'file' - @model.expects(:new).with(content).returns(file) + File.expects(:exist?).with(@path).returns(true) + File.expects(:read).with(@path).returns(content) + @searcher.find(@path) + end - File.expects(:exist?).with(@path).returns(true) - File.expects(:read).with(@path).returns(content) - @searcher.find(@path) - end + it "should create the model instance with the content as the only argument to initialization" do + content = "my content" - it "should create the model instance with the content as the only argument to initialization" do - content = "my content" + file = mock 'file' + @model.expects(:new).with(content).returns(file) - file = mock 'file' - @model.expects(:new).with(content).returns(file) + File.expects(:exist?).with(@path).returns(true) + File.expects(:read).with(@path).returns(content) + @searcher.find(@path).should equal(file) + end - File.expects(:exist?).with(@path).returns(true) - File.expects(:read).with(@path).returns(content) - @searcher.find(@path).should equal(file) - end + it "should return nil if no file is found" do + File.expects(:exist?).with(@path).returns(false) + @searcher.find(@path).should be_nil + end - it "should return nil if no file is found" do - File.expects(:exist?).with(@path).returns(false) - @searcher.find(@path).should be_nil - end + it "should fail intelligently if a found file cannot be read" do + File.expects(:exist?).with(@path).returns(true) + File.expects(:read).with(@path).raises(RuntimeError) + proc { @searcher.find(@path) }.should raise_error(Puppet::Error) + end - it "should fail intelligently if a found file cannot be read" do - File.expects(:exist?).with(@path).returns(true) - File.expects(:read).with(@path).raises(RuntimeError) - proc { @searcher.find(@path) }.should raise_error(Puppet::Error) - end + it "should use the path() method to calculate the path if it exists" do + @searcher.meta_def(:path) do |name| + name.upcase + end - it "should use the path() method to calculate the path if it exists" do - @searcher.meta_def(:path) do |name| - name.upcase + File.expects(:exist?).with(@path.upcase).returns(false) + @searcher.find(@path) end - - File.expects(:exist?).with(@path.upcase).returns(false) - @searcher.find(@path) end -end -describe Puppet::Indirector::File, " when saving files" do - include FileTerminusTesting + describe Puppet::Indirector::File, " when saving files" do - it "should provide a method to save file contents at a specified path" do - filehandle = mock 'file' - content = "my content" - File.expects(:directory?).with(@dir).returns(true) - File.expects(:open).with(@path, "w").yields(filehandle) - filehandle.expects(:print).with(content) + it "should provide a method to save file contents at a specified path" do + filehandle = mock 'file' + content = "my content" + File.expects(:directory?).with(@dir).returns(true) + File.expects(:open).with(@path, "w").yields(filehandle) + filehandle.expects(:print).with(content) - file = stub 'file', :content => content, :path => @path, :name => @path + file = stub 'file', :content => content, :path => @path, :name => @path - @searcher.save(file) - end + @searcher.save(file) + end - it "should fail intelligently if the file's parent directory does not exist" do - File.expects(:directory?).with(@dir).returns(false) + it "should fail intelligently if the file's parent directory does not exist" do + File.expects(:directory?).with(@dir).returns(false) - file = stub 'file', :path => @path, :name => @path + file = stub 'file', :path => @path, :name => @path - proc { @searcher.save(file) }.should raise_error(Puppet::Error) - end - - it "should fail intelligently if a file cannot be written" do - filehandle = mock 'file' - content = "my content" - File.expects(:directory?).with(@dir).returns(true) - File.expects(:open).with(@path, "w").yields(filehandle) - filehandle.expects(:print).with(content).raises(ArgumentError) + proc { @searcher.save(file) }.should raise_error(Puppet::Error) + end - file = stub 'file', :content => content, :path => @path, :name => @path + it "should fail intelligently if a file cannot be written" do + filehandle = mock 'file' + content = "my content" + File.expects(:directory?).with(@dir).returns(true) + File.expects(:open).with(@path, "w").yields(filehandle) + filehandle.expects(:print).with(content).raises(ArgumentError) - proc { @searcher.save(file) }.should raise_error(Puppet::Error) - end + file = stub 'file', :content => content, :path => @path, :name => @path - it "should use the path() method to calculate the path if it exists" do - @searcher.meta_def(:path) do |name| - name.upcase + proc { @searcher.save(file) }.should raise_error(Puppet::Error) end - file = stub 'file', :name => "/yay" + it "should use the path() method to calculate the path if it exists" do + @searcher.meta_def(:path) do |name| + name.upcase + end + + file = stub 'file', :name => "/yay" - File.expects(:open).with("/YAY", "w") - @searcher.save(file) + File.expects(:open).with("/YAY", "w") + @searcher.save(file) + end end -end -describe Puppet::Indirector::File, " when removing files" do - include FileTerminusTesting + describe Puppet::Indirector::File, " when removing files" do - it "should provide a method to remove files at a specified path" do - file = stub 'file', :path => @path, :name => @path - File.expects(:exist?).with(@path).returns(true) - File.expects(:unlink).with(@path) - - @searcher.destroy(file) - end + it "should provide a method to remove files at a specified path" do + file = stub 'file', :path => @path, :name => @path + File.expects(:exist?).with(@path).returns(true) + File.expects(:unlink).with(@path) - it "should throw an exception if the file is not found" do - file = stub 'file', :path => @path, :name => @path - File.expects(:exist?).with(@path).returns(false) + @searcher.destroy(file) + end - proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) - end + it "should throw an exception if the file is not found" do + file = stub 'file', :path => @path, :name => @path + File.expects(:exist?).with(@path).returns(false) - it "should fail intelligently if the file cannot be removed" do - file = stub 'file', :path => @path, :name => @path - File.expects(:exist?).with(@path).returns(true) - File.expects(:unlink).with(@path).raises(ArgumentError) + proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) + end - proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) - end + it "should fail intelligently if the file cannot be removed" do + file = stub 'file', :path => @path, :name => @path + File.expects(:exist?).with(@path).returns(true) + File.expects(:unlink).with(@path).raises(ArgumentError) - it "should use the path() method to calculate the path if it exists" do - @searcher.meta_def(:path) do |name| - name.upcase + proc { @searcher.destroy(file) }.should raise_error(Puppet::Error) end - file = stub 'file', :name => "/yay" - File.expects(:exist?).with("/YAY").returns(true) - File.expects(:unlink).with("/YAY") + it "should use the path() method to calculate the path if it exists" do + @searcher.meta_def(:path) do |name| + name.upcase + end + + file = stub 'file', :name => "/yay" + File.expects(:exist?).with("/YAY").returns(true) + File.expects(:unlink).with("/YAY") - @searcher.destroy(file) + @searcher.destroy(file) + end end -end +end \ No newline at end of file diff --git a/spec/unit/indirector/file_server.rb b/spec/unit/indirector/file_server.rb index fda60f1ec..974b95e0e 100755 --- a/spec/unit/indirector/file_server.rb +++ b/spec/unit/indirector/file_server.rb @@ -1,173 +1,168 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-10-19. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/file_server' require 'puppet/file_serving/configuration' -module FileServerTerminusTesting - def setup +describe Puppet::Indirector::FileServer do + + before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @model = mock 'model' @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) @file_server_class = Class.new(Puppet::Indirector::FileServer) do def self.to_s "Testing::Mytype" end end @file_server = @file_server_class.new @uri = "puppetmounts://host/my/local/file" @configuration = mock 'configuration' Puppet::FileServing::Configuration.stubs(:create).returns(@configuration) end -end -describe Puppet::Indirector::FileServer, " when finding files" do - include FileServerTerminusTesting + describe Puppet::Indirector::FileServer, " when finding files" do - it "should use the path portion of the URI as the file name" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil) - @file_server.find(@uri) - end + it "should use the path portion of the URI as the file name" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil) + @file_server.find(@uri) + end - it "should use the FileServing configuration to convert the file name to a fully qualified path" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil) - @file_server.find(@uri) - end + it "should use the FileServing configuration to convert the file name to a fully qualified path" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil) + @file_server.find(@uri) + end - it "should pass the node name to the FileServing configuration if one is provided" do - @configuration.expects(:file_path).with("/my/local/file", :node => "testing") - @file_server.find(@uri, :node => "testing") - end + it "should pass the node name to the FileServing configuration if one is provided" do + @configuration.expects(:file_path).with("/my/local/file", :node => "testing") + @file_server.find(@uri, :node => "testing") + end - it "should return nil if no fully qualified path is found" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) - @file_server.find(@uri).should be_nil - end + it "should return nil if no fully qualified path is found" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) + @file_server.find(@uri).should be_nil + end - it "should return an instance of the model created with the full path if a file is found" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") - @model.expects(:new).returns(:myinstance) - @file_server.find(@uri).should == :myinstance + it "should return an instance of the model created with the full path if a file is found" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") + @model.expects(:new).returns(:myinstance) + @file_server.find(@uri).should == :myinstance + end end -end + describe Puppet::Indirector::FileServer, " when returning instances" do + before :each do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") + @instance = mock 'instance' + end -describe Puppet::Indirector::FileServer, " when returning instances" do - include FileServerTerminusTesting - - before do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/some/file") - @instance = mock 'instance' - end - - it "should create the instance with the key used to find the instance" do - @model.expects(:new).with { |key, *options| key == @uri } - @file_server.find(@uri) - end + it "should create the instance with the key used to find the instance" do + @model.expects(:new).with { |key, *options| key == @uri } + @file_server.find(@uri) + end - it "should create the instance with the path at which the instance was found" do - @model.expects(:new).with { |key, options| options[:path] == "/some/file" } - @file_server.find(@uri) - end + it "should create the instance with the path at which the instance was found" do + @model.expects(:new).with { |key, options| options[:path] == "/some/file" } + @file_server.find(@uri) + end - it "should set the provided :links setting on to the instance if one is provided" do - @model.expects(:new).returns(@instance) - @instance.expects(:links=).with(:mytest) - @file_server.find(@uri, :links => :mytest) - end + it "should set the provided :links setting on to the instance if one is provided" do + @model.expects(:new).returns(@instance) + @instance.expects(:links=).with(:mytest) + @file_server.find(@uri, :links => :mytest) + end - it "should not set a :links value if no :links parameter is provided" do - @model.expects(:new).returns(@instance) - @file_server.find(@uri) + it "should not set a :links value if no :links parameter is provided" do + @model.expects(:new).returns(@instance) + @file_server.find(@uri) + end end -end -describe Puppet::Indirector::FileServer, " when checking authorization" do - include FileServerTerminusTesting + describe Puppet::Indirector::FileServer, " when checking authorization" do - it "should have an authorization hook" do - @file_server.should respond_to(:authorized?) - end + it "should have an authorization hook" do + @file_server.should respond_to(:authorized?) + end - it "should deny the :destroy method" do - @file_server.authorized?(:destroy, "whatever").should be_false - end + it "should deny the :destroy method" do + @file_server.authorized?(:destroy, "whatever").should be_false + end - it "should deny the :save method" do - @file_server.authorized?(:save, "whatever").should be_false - end + it "should deny the :save method" do + @file_server.authorized?(:save, "whatever").should be_false + end - it "should use the file server configuration to determine authorization" do - @configuration.expects(:authorized?) - @file_server.authorized?(:find, "puppetmounts://host/my/file") - end + it "should use the file server configuration to determine authorization" do + @configuration.expects(:authorized?) + @file_server.authorized?(:find, "puppetmounts://host/my/file") + end - it "should pass the file path from the URI to the file server configuration" do - @configuration.expects(:authorized?).with { |uri, *args| uri == "/my/file" } - @file_server.authorized?(:find, "puppetmounts://host/my/file") - end + it "should pass the file path from the URI to the file server configuration" do + @configuration.expects(:authorized?).with { |uri, *args| uri == "/my/file" } + @file_server.authorized?(:find, "puppetmounts://host/my/file") + end - it "should pass the node name to the file server configuration" do - @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" } - @file_server.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode") - end + it "should pass the node name to the file server configuration" do + @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" } + @file_server.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode") + end - it "should pass the IP address to the file server configuration" do - @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" } - @file_server.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip") - end + it "should pass the IP address to the file server configuration" do + @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" } + @file_server.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip") + end - it "should return false if the file server configuration denies authorization" do - @configuration.expects(:authorized?).returns(false) - @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_false - end + it "should return false if the file server configuration denies authorization" do + @configuration.expects(:authorized?).returns(false) + @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_false + end - it "should return true if the file server configuration approves authorization" do - @configuration.expects(:authorized?).returns(true) - @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_true + it "should return true if the file server configuration approves authorization" do + @configuration.expects(:authorized?).returns(true) + @file_server.authorized?(:find, "puppetmounts://host/my/file").should be_true + end end -end -describe Puppet::Indirector::FileServer, " when searching for files" do - include FileServerTerminusTesting + describe Puppet::Indirector::FileServer, " when searching for files" do - it "should use the path portion of the URI as the file name" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil) - @file_server.search(@uri) - end + it "should use the path portion of the URI as the file name" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil) + @file_server.search(@uri) + end - it "should use the FileServing configuration to convert the file name to a fully qualified path" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil) - @file_server.search(@uri) - end + it "should use the FileServing configuration to convert the file name to a fully qualified path" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil) + @file_server.search(@uri) + end - it "should pass the node name to the FileServing configuration if one is provided" do - @configuration.expects(:file_path).with("/my/local/file", :node => "testing") - @file_server.search(@uri, :node => "testing") - end + it "should pass the node name to the FileServing configuration if one is provided" do + @configuration.expects(:file_path).with("/my/local/file", :node => "testing") + @file_server.search(@uri, :node => "testing") + end - it "should return nil if no fully qualified path is found" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) - @file_server.search(@uri).should be_nil - end + it "should return nil if no fully qualified path is found" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns(nil) + @file_server.search(@uri).should be_nil + end - it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") - @file_server.expects(:path2instances).with(@uri, "/my/file", {}) - @file_server.search(@uri) - end + it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") + @file_server.expects(:path2instances).with(@uri, "/my/file", {}) + @file_server.search(@uri) + end - it "should pass any options on to :path2instances" do - @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") - @file_server.expects(:path2instances).with(@uri, "/my/file", :testing => :one, :other => :two) - @file_server.search(@uri, :testing => :one, :other => :two) + it "should pass any options on to :path2instances" do + @configuration.expects(:file_path).with("/my/local/file", :node => nil).returns("/my/file") + @file_server.expects(:path2instances).with(@uri, "/my/file", :testing => :one, :other => :two) + @file_server.search(@uri, :testing => :one, :other => :two) + end end -end +end \ No newline at end of file diff --git a/spec/unit/indirector/indirection.rb b/spec/unit/indirector/indirection.rb index 36192b8e5..fe456b61e 100755 --- a/spec/unit/indirector/indirection.rb +++ b/spec/unit/indirector/indirection.rb @@ -1,585 +1,580 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector' -module IndirectionTesting - def setup - @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) - @terminus = stub 'terminus', :has_most_recent? => false - @indirection.stubs(:terminus).returns(@terminus) - @indirection.stubs(:terminus_class).returns(:whatever) - @instance = stub 'instance', :version => nil, :version= => nil, :name => "whatever" - @name = :mything - end - - def teardown - @indirection.delete - Puppet::Indirector::Indirection.clear_cache - end -end + describe Puppet::Indirector::Indirection, " 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 proc { @indirection = Puppet::Indirector::Indirection.new(Object.new, :testingness, :not_valid_option) }.should raise_error Puppet::Indirector::Indirection.instance(:testingness).should be_instance_of(Puppet::Indirector::Indirection) Puppet::Indirector::Indirection.instance(:testingness).delete end it "should keep a reference to the indirecting model" do model = mock 'model' @indirection = Puppet::Indirector::Indirection.new(model, :myind) @indirection.model.should equal(model) end it "should set the name" do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :myind) @indirection.name.should == :myind end it "should require indirections to have unique names" do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) proc { Puppet::Indirector::Indirection.new(:test) }.should raise_error(ArgumentError) end it "should extend itself with any specified module" do mod = Module.new @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test, :extend => mod) @indirection.metaclass.included_modules.should include(mod) end after do @indirection.delete if defined? @indirection end end -describe Puppet::Indirector::Indirection, " when looking for a model instance" do - include IndirectionTesting +describe Puppet::Indirector::Indirection do + before :each do + @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) + @terminus = stub 'terminus', :has_most_recent? => false + @indirection.stubs(:terminus).returns(@terminus) + @indirection.stubs(:terminus_class).returns(:whatever) + @instance = stub 'instance', :version => nil, :version= => nil, :name => "whatever" + @name = :mything + end + + describe Puppet::Indirector::Indirection, " when looking for a model instance" do + + it "should let the appropriate terminus perform the lookup" do + @terminus.expects(:find).with(@name).returns(@instance) + @indirection.find(@name).should == @instance + end + + it "should not attempt to set a timestamp if the terminus cannot find the instance" do + @terminus.expects(:find).with(@name).returns(nil) + proc { @indirection.find(@name) }.should_not raise_error + end - it "should let the appropriate terminus perform the lookup" do - @terminus.expects(:find).with(@name).returns(@instance) - @indirection.find(@name).should == @instance + it "should pass the instance to the :post_find hook if there is one" do + class << @terminus + def post_find + end + end + @terminus.expects(:post_find).with(@instance) + @terminus.expects(:find).with(@name).returns(@instance) + @indirection.find(@name) + end end + + describe Puppet::Indirector::Indirection, " when removing a model instance" do - it "should not attempt to set a timestamp if the terminus cannot find the instance" do - @terminus.expects(:find).with(@name).returns(nil) - proc { @indirection.find(@name) }.should_not raise_error + it "should let the appropriate terminus remove the instance" do + @terminus.expects(:destroy).with(@name).returns(@instance) + @indirection.destroy(@name).should == @instance + end end - it "should pass the instance to the :post_find hook if there is one" do - class << @terminus - def post_find + describe Puppet::Indirector::Indirection, " when searching for multiple model instances" do + + it "should let the appropriate terminus find the matching instances" do + @terminus.expects(:search).with(@name).returns(@instance) + @indirection.search(@name).should == @instance + end + + it "should pass the instances to the :post_search hook if there is one" do + class << @terminus + def post_search + end end + @terminus.expects(:post_search).with(@instance) + @terminus.expects(:search).with(@name).returns(@instance) + @indirection.search(@name) end - @terminus.expects(:post_find).with(@instance) - @terminus.expects(:find).with(@name).returns(@instance) - @indirection.find(@name) end -end -describe Puppet::Indirector::Indirection, " when removing a model instance" do - include IndirectionTesting + describe Puppet::Indirector::Indirection, " when storing a model instance" do - it "should let the appropriate terminus remove the instance" do - @terminus.expects(:destroy).with(@name).returns(@instance) - @indirection.destroy(@name).should == @instance + it "should let the appropriate terminus store the instance" do + @terminus.expects(:save).with(@instance).returns(@instance) + @indirection.save(@instance).should == @instance + end end -end + + describe Puppet::Indirector::Indirection, " when handling instance versions" do -describe Puppet::Indirector::Indirection, " when searching for multiple model instances" do - include IndirectionTesting - - it "should let the appropriate terminus find the matching instances" do - @terminus.expects(:search).with(@name).returns(@instance) - @indirection.search(@name).should == @instance - end + it "should let the appropriate terminus perform the lookup" do + @terminus.expects(:version).with(@name).returns(5) + @indirection.version(@name).should == 5 + end + + it "should add versions to found instances that do not already have them" do + @terminus.expects(:find).with(@name).returns(@instance) + time = mock 'time' + time.expects(:utc).returns(:mystamp) + Time.expects(:now).returns(time) + @instance.expects(:version=).with(:mystamp) + @indirection.find(@name) + end + + it "should add versions to saved instances that do not already have them" do + time = mock 'time' + time.expects(:utc).returns(:mystamp) + Time.expects(:now).returns(time) + @instance.expects(:version=).with(:mystamp) + @terminus.stubs(:save) + @indirection.save(@instance) + end - it "should pass the instances to the :post_search hook if there is one" do - class << @terminus - def post_search + # We've already tested this, basically, but... + it "should use the current time in UTC for versions" do + @instance.expects(:version=).with do |time| + time.utc? end + @terminus.stubs(:save) + @indirection.save(@instance) end - @terminus.expects(:post_search).with(@instance) - @terminus.expects(:search).with(@name).returns(@instance) - @indirection.search(@name) end -end -describe Puppet::Indirector::Indirection, " when storing a model instance" do - include IndirectionTesting - - it "should let the appropriate terminus store the instance" do - @terminus.expects(:save).with(@instance).returns(@instance) - @indirection.save(@instance).should == @instance - end -end -describe Puppet::Indirector::Indirection, " when handling instance versions" do - include IndirectionTesting - - it "should let the appropriate terminus perform the lookup" do - @terminus.expects(:version).with(@name).returns(5) - @indirection.version(@name).should == 5 - end + describe Puppet::Indirector::Indirection, " when an authorization hook is present" do - it "should add versions to found instances that do not already have them" do - @terminus.expects(:find).with(@name).returns(@instance) - time = mock 'time' - time.expects(:utc).returns(:mystamp) - Time.expects(:now).returns(time) - @instance.expects(:version=).with(:mystamp) - @indirection.find(@name) - end + before do + # So the :respond_to? turns out right. + class << @terminus + def authorized? + end + end + end - it "should add versions to saved instances that do not already have them" do - time = mock 'time' - time.expects(:utc).returns(:mystamp) - Time.expects(:now).returns(time) - @instance.expects(:version=).with(:mystamp) - @terminus.stubs(:save) - @indirection.save(@instance) - end + it "should not check authorization if a node name is not provided" do + @terminus.expects(:authorized?).never + @terminus.stubs(:find) + @indirection.find("/my/key") + end + + it "should fail while finding instances if authorization returns false" do + @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(false) + @terminus.stubs(:find) + proc { @indirection.find("/my/key", :node => "mynode") }.should raise_error(ArgumentError) + end + + it "should continue finding instances if authorization returns true" do + @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(true) + @terminus.stubs(:find) + @indirection.find("/my/key", :node => "mynode") + end + + it "should fail while saving instances if authorization returns false" do + @terminus.expects(:authorized?).with(:save, :myinstance, :node => "mynode").returns(false) + @terminus.stubs(:save) + proc { @indirection.save(:myinstance, :node => "mynode") }.should raise_error(ArgumentError) + end + + it "should continue saving instances if authorization returns true" do + instance = stub 'instance', :version => 1.0, :name => "eh" + @terminus.expects(:authorized?).with(:save, instance, :node => "mynode").returns(true) + @terminus.stubs(:save) + @indirection.save(instance, :node => "mynode") + end + + it "should fail while destroying instances if authorization returns false" do + @terminus.expects(:authorized?).with(:destroy, "/my/key", :node => "mynode").returns(false) + @terminus.stubs(:destroy) + proc { @indirection.destroy("/my/key", :node => "mynode") }.should raise_error(ArgumentError) + end + + it "should continue destroying instances if authorization returns true" do + instance = stub 'instance', :version => 1.0, :name => "eh" + @terminus.expects(:authorized?).with(:destroy, instance, :node => "mynode").returns(true) + @terminus.stubs(:destroy) + @indirection.destroy(instance, :node => "mynode") + end + + it "should fail while searching for instances if authorization returns false" do + @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(false) + @terminus.stubs(:search) + proc { @indirection.search("/my/key", :node => "mynode") }.should raise_error(ArgumentError) + end - # We've already tested this, basically, but... - it "should use the current time in UTC for versions" do - @instance.expects(:version=).with do |time| - time.utc? + it "should continue searching for instances if authorization returns true" do + @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(true) + @terminus.stubs(:search) + @indirection.search("/my/key", :node => "mynode") end - @terminus.stubs(:save) - @indirection.save(@instance) + end + + after :each do + @indirection.delete + Puppet::Indirector::Indirection.clear_cache end end + describe Puppet::Indirector::Indirection, " when managing indirection instances" do it "should allow an indirection to be retrieved by name" do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) Puppet::Indirector::Indirection.instance(:test).should equal(@indirection) end it "should return nil when the named indirection has not been created" do Puppet::Indirector::Indirection.instance(:test).should be_nil end it "should allow an indirection's model to be retrieved by name" do mock_model = mock('model') @indirection = Puppet::Indirector::Indirection.new(mock_model, :test) Puppet::Indirector::Indirection.model(:test).should equal(mock_model) end it "should return nil when no model matches the requested name" do Puppet::Indirector::Indirection.model(:test).should be_nil end after do @indirection.delete if defined? @indirection end end describe Puppet::Indirector::Indirection, " when choosing the terminus class" do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = stub 'terminus class', :new => @terminus Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :default).returns(@terminus_class) end it "should choose the default terminus class if one is specified and no specific terminus class is provided" do @indirection.terminus_class = :default @indirection.terminus_class.should equal(:default) end it "should use the provided Puppet setting if told to do so" do Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :my_terminus).returns(mock("terminus_class2")) Puppet.settings.expects(:value).with(:my_setting).returns("my_terminus") @indirection.terminus_setting = :my_setting @indirection.terminus_class.should equal(:my_terminus) end it "should fail if the provided terminus class is not valid" do Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :nosuchclass).returns(nil) proc { @indirection.terminus_class = :nosuchclass }.should raise_error(ArgumentError) end it "should fail if no terminus class is picked" do proc { @indirection.terminus_class }.should raise_error(Puppet::DevError) end after do @indirection.delete if defined? @indirection end end describe Puppet::Indirector::Indirection, " when specifying the terminus class to use" do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = stub 'terminus class', :new => @terminus end it "should allow specification of a terminus type" do @indirection.should respond_to(:terminus_class=) end it "should fail to redirect if no terminus type has been specified" do proc { @indirection.find("blah") }.should raise_error(Puppet::DevError) end it "should fail when the terminus class name is an empty string" do proc { @indirection.terminus_class = "" }.should raise_error(ArgumentError) end it "should fail when the terminus class name is nil" do proc { @indirection.terminus_class = nil }.should raise_error(ArgumentError) end it "should fail when the specified terminus class cannot be found" do Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil) proc { @indirection.terminus_class = :foo }.should raise_error(ArgumentError) end it "should select the specified terminus class if a terminus class name is provided" do Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(@terminus_class) @indirection.terminus(:foo).should equal(@terminus) end it "should use the configured terminus class if no terminus name is specified" do Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class) @indirection.terminus_class = :foo @indirection.terminus().should equal(@terminus) end after do @indirection.delete if defined? @indirection end end describe Puppet::Indirector::Indirection, " when a select_terminus hook is available" do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) # And provide a select_terminus hook @indirection.meta_def(:select_terminus) do |uri| :other end @terminus = mock 'terminus' @terminus_class = stub 'terminus class', :new => @terminus @other_terminus = mock 'other_terminus' @other_terminus_class = stub 'other_terminus_class', :new => @other_terminus @cache_terminus = mock 'cache_terminus' @cache_terminus_class = stub 'cache_terminus_class', :new => @cache_terminus Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class) Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :other).returns(@other_terminus_class) Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache).returns(@cache_terminus_class) # Set it to a default type. @indirection.terminus_class = :foo @uri = "full://url/path" @result = stub 'result', :version => 1.0 end it "should use the terminus name provided by passing the key to the :select_terminus hook when finding instances" do # Set up the expectation @other_terminus.expects(:find).with(@uri).returns(@result) @indirection.find(@uri) end it "should use the terminus name provided by passing the key to the :select_terminus hook when testing if a cached instance is up to date" do @indirection.cache_class = :cache @other_terminus.expects(:version).with(@uri).returns(2.0) @cache_terminus.expects(:has_most_recent?).with(@uri, 2.0).returns(true) @cache_terminus.expects(:find).returns(:whatever) @indirection.find(@uri).should == :whatever end it "should pass all arguments to the :select_terminus hook" do @indirection.expects(:select_terminus).with(@uri, :node => "johnny").returns(:other) @other_terminus.stubs(:find) @indirection.find(@uri, :node => "johnny") end it "should pass the original key to the terminus rather than a modified key" do # This is the same test as before @other_terminus.expects(:find).with(@uri).returns(@result) @indirection.find(@uri) end after do @indirection.delete if defined? @indirection end end describe Puppet::Indirector::Indirection, " when managing terminus instances" do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = mock 'terminus class' Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class) end it "should create an instance of the chosen terminus class" do @terminus_class.stubs(:new).returns(@terminus) @indirection.terminus(:foo).should equal(@terminus) end it "should allow the clearance of cached terminus instances" do terminus1 = mock 'terminus1' terminus2 = mock 'terminus2' @terminus_class.stubs(:new).returns(terminus1, terminus2, ArgumentError) @indirection.terminus(:foo).should equal(terminus1) @indirection.class.clear_cache @indirection.terminus(:foo).should equal(terminus2) end # Make sure it caches the terminus. it "should return the same terminus instance each time for a given name" do @terminus_class.stubs(:new).returns(@terminus) @indirection.terminus(:foo).should equal(@terminus) @indirection.terminus(:foo).should equal(@terminus) end it "should not create a terminus instance until one is actually needed" do Puppet::Indirector.expects(:terminus).never indirection = Puppet::Indirector::Indirection.new(mock('model'), :lazytest) end after do @indirection.delete Puppet::Indirector::Indirection.clear_cache end end describe Puppet::Indirector::Indirection, " when deciding whether to cache" do before do @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @terminus = mock 'terminus' @terminus_class = mock 'terminus class' @terminus_class.stubs(:new).returns(@terminus) Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :foo).returns(@terminus_class) @indirection.terminus_class = :foo end it "should provide a method for setting the cache terminus class" do @indirection.should respond_to(:cache_class=) end it "should fail to cache if no cache type has been specified" do proc { @indirection.cache }.should raise_error(Puppet::DevError) end it "should fail to set the cache class when the cache class name is an empty string" do proc { @indirection.cache_class = "" }.should raise_error(ArgumentError) end it "should fail to set the cache class when the cache class name is nil" do proc { @indirection.cache_class = nil }.should raise_error(ArgumentError) end it "should fail to set the cache class when the specified cache class cannot be found" do Puppet::Indirector::Terminus.expects(:terminus_class).with(:test, :foo).returns(nil) proc { @indirection.cache_class = :foo }.should raise_error(ArgumentError) end after do @indirection.delete Puppet::Indirector::Indirection.clear_cache end end -module IndirectionCacheTesting - def setup +describe Puppet::Indirector::Indirection do + before :each do Puppet.settings.stubs(:value).with("test_terminus").returns("test_terminus") @terminus_class = mock 'terminus_class' @terminus = mock 'terminus' @terminus_class.stubs(:new).returns(@terminus) @cache = mock 'cache' @cache_class = mock 'cache_class' Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :cache_terminus).returns(@cache_class) Puppet::Indirector::Terminus.stubs(:terminus_class).with(:test, :test_terminus).returns(@terminus_class) @indirection = Puppet::Indirector::Indirection.new(mock('model'), :test) @indirection.terminus_class = :test_terminus end - def teardown - @indirection.delete - Puppet::Indirector::Indirection.clear_cache - end -end - -describe Puppet::Indirector::Indirection, " when managing the cache terminus" do - include IndirectionCacheTesting - - it "should not create a cache terminus at initialization" do - # This is weird, because all of the code is in the setup. If we got - # new() called on the cache class, we'd get an exception here. - end - - it "should reuse the cache terminus" do - @cache_class.expects(:new).returns(@cache) - Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus") - @indirection.cache_class = :cache_terminus - @indirection.cache.should equal(@cache) - @indirection.cache.should equal(@cache) - end - - it "should remove the cache terminus when all other terminus instances are cleared" do - cache2 = mock 'cache2' - @cache_class.stubs(:new).returns(@cache, cache2) - @indirection.cache_class = :cache_terminus - @indirection.cache.should equal(@cache) - @indirection.clear_cache - @indirection.cache.should equal(cache2) - end -end - -describe Puppet::Indirector::Indirection, " when saving and using a cache" do - include IndirectionCacheTesting - - before do - @indirection.cache_class = :cache_terminus - @cache_class.expects(:new).returns(@cache) - @name = "testing" - @instance = stub 'instance', :version => 5, :name => @name - end - - it "should not update the cache or terminus if the new object is not different" do - @cache.expects(:has_most_recent?).with(@name, 5).returns(true) - @indirection.save(@instance) - end + describe Puppet::Indirector::Indirection, " when managing the cache terminus" do - it "should update the original and the cache if the cached object is different" do - @cache.expects(:has_most_recent?).with(@name, 5).returns(false) - @terminus.expects(:save).with(@instance) - @cache.expects(:save).with(@instance) - @indirection.save(@instance) - end -end + it "should not create a cache terminus at initialization" do + # This is weird, because all of the code is in the setup. If we got + # new() called on the cache class, we'd get an exception here. + end -describe Puppet::Indirector::Indirection, " when finding and using a cache" do - include IndirectionCacheTesting + it "should reuse the cache terminus" do + @cache_class.expects(:new).returns(@cache) + Puppet.settings.stubs(:value).with("test_cache").returns("cache_terminus") + @indirection.cache_class = :cache_terminus + @indirection.cache.should equal(@cache) + @indirection.cache.should equal(@cache) + end - before do - @indirection.cache_class = :cache_terminus - @cache_class.expects(:new).returns(@cache) + it "should remove the cache terminus when all other terminus instances are cleared" do + cache2 = mock 'cache2' + @cache_class.stubs(:new).returns(@cache, cache2) + @indirection.cache_class = :cache_terminus + @indirection.cache.should equal(@cache) + @indirection.clear_cache + @indirection.cache.should equal(cache2) + end end - it "should return the cached object if the cache is up to date" do - cached = mock 'cached object' + describe Puppet::Indirector::Indirection, " when saving and using a cache" do - name = "myobject" - - @terminus.expects(:version).with(name).returns(1) - @cache.expects(:has_most_recent?).with(name, 1).returns(true) + before do + @indirection.cache_class = :cache_terminus + @cache_class.expects(:new).returns(@cache) + @name = "testing" + @instance = stub 'instance', :version => 5, :name => @name + end - @cache.expects(:find).with(name).returns(cached) + it "should not update the cache or terminus if the new object is not different" do + @cache.expects(:has_most_recent?).with(@name, 5).returns(true) + @indirection.save(@instance) + end - @indirection.find(name).should equal(cached) + it "should update the original and the cache if the cached object is different" do + @cache.expects(:has_most_recent?).with(@name, 5).returns(false) + @terminus.expects(:save).with(@instance) + @cache.expects(:save).with(@instance) + @indirection.save(@instance) + end end + + describe Puppet::Indirector::Indirection, " when finding and using a cache" do - it "should return the original object if the cache is not up to date" do - real = stub 'real object', :version => 1 - - name = "myobject" + before do + @indirection.cache_class = :cache_terminus + @cache_class.expects(:new).returns(@cache) + end - @cache.stubs(:save) - @cache.expects(:has_most_recent?).with(name, 1).returns(false) - @terminus.expects(:version).with(name).returns(1) + it "should return the cached object if the cache is up to date" do + cached = mock 'cached object' - @terminus.expects(:find).with(name).returns(real) + name = "myobject" - @indirection.find(name).should equal(real) - end + @terminus.expects(:version).with(name).returns(1) + @cache.expects(:has_most_recent?).with(name, 1).returns(true) - it "should cache any newly returned objects" do - real = stub 'real object', :version => 1 + @cache.expects(:find).with(name).returns(cached) - name = "myobject" + @indirection.find(name).should equal(cached) + end - @terminus.expects(:version).with(name).returns(1) - @cache.expects(:has_most_recent?).with(name, 1).returns(false) + it "should return the original object if the cache is not up to date" do + real = stub 'real object', :version => 1 - @terminus.expects(:find).with(name).returns(real) - @cache.expects(:save).with(real) + name = "myobject" - @indirection.find(name).should equal(real) - end -end + @cache.stubs(:save) + @cache.expects(:has_most_recent?).with(name, 1).returns(false) + @terminus.expects(:version).with(name).returns(1) -describe Puppet::Indirector::Indirection, " when an authorization hook is present" do - include IndirectionTesting + @terminus.expects(:find).with(name).returns(real) - before do - # So the :respond_to? turns out right. - class << @terminus - def authorized? - end + @indirection.find(name).should equal(real) end - end - it "should not check authorization if a node name is not provided" do - @terminus.expects(:authorized?).never - @terminus.stubs(:find) - @indirection.find("/my/key") - end - - it "should fail while finding instances if authorization returns false" do - @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(false) - @terminus.stubs(:find) - proc { @indirection.find("/my/key", :node => "mynode") }.should raise_error(ArgumentError) - end - - it "should continue finding instances if authorization returns true" do - @terminus.expects(:authorized?).with(:find, "/my/key", :node => "mynode").returns(true) - @terminus.stubs(:find) - @indirection.find("/my/key", :node => "mynode") - end + it "should cache any newly returned objects" do + real = stub 'real object', :version => 1 - it "should fail while saving instances if authorization returns false" do - @terminus.expects(:authorized?).with(:save, :myinstance, :node => "mynode").returns(false) - @terminus.stubs(:save) - proc { @indirection.save(:myinstance, :node => "mynode") }.should raise_error(ArgumentError) - end + name = "myobject" - it "should continue saving instances if authorization returns true" do - instance = stub 'instance', :version => 1.0, :name => "eh" - @terminus.expects(:authorized?).with(:save, instance, :node => "mynode").returns(true) - @terminus.stubs(:save) - @indirection.save(instance, :node => "mynode") - end + @terminus.expects(:version).with(name).returns(1) + @cache.expects(:has_most_recent?).with(name, 1).returns(false) - it "should fail while destroying instances if authorization returns false" do - @terminus.expects(:authorized?).with(:destroy, "/my/key", :node => "mynode").returns(false) - @terminus.stubs(:destroy) - proc { @indirection.destroy("/my/key", :node => "mynode") }.should raise_error(ArgumentError) - end + @terminus.expects(:find).with(name).returns(real) + @cache.expects(:save).with(real) - it "should continue destroying instances if authorization returns true" do - instance = stub 'instance', :version => 1.0, :name => "eh" - @terminus.expects(:authorized?).with(:destroy, instance, :node => "mynode").returns(true) - @terminus.stubs(:destroy) - @indirection.destroy(instance, :node => "mynode") - end - - it "should fail while searching for instances if authorization returns false" do - @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(false) - @terminus.stubs(:search) - proc { @indirection.search("/my/key", :node => "mynode") }.should raise_error(ArgumentError) + @indirection.find(name).should equal(real) + end end - - it "should continue searching for instances if authorization returns true" do - @terminus.expects(:authorized?).with(:search, "/my/key", :node => "mynode").returns(true) - @terminus.stubs(:search) - @indirection.search("/my/key", :node => "mynode") + + after :each do + @indirection.delete + Puppet::Indirector::Indirection.clear_cache end end diff --git a/spec/unit/indirector/module_files.rb b/spec/unit/indirector/module_files.rb index 9011530dd..0f6dbb6df 100755 --- a/spec/unit/indirector/module_files.rb +++ b/spec/unit/indirector/module_files.rb @@ -1,245 +1,243 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-10-19. # Copyright (c) 2007. All rights reserved. require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/module_files' -module ModuleFilesTerminusTesting - def setup - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Indirector::Terminus.stubs(:register_terminus_class) - @model = mock 'model' - @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model - Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) - @module_files_class = Class.new(Puppet::Indirector::ModuleFiles) do - def self.to_s - "Testing::Mytype" - end - end +describe Puppet::Indirector::ModuleFiles do - @module_files = @module_files_class.new + before :each do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Indirector::Terminus.stubs(:register_terminus_class) + @model = mock 'model' + @indirection = stub 'indirection', :name => :mystuff, :register_terminus_type => nil, :model => @model + Puppet::Indirector::Indirection.stubs(:instance).returns(@indirection) - @uri = "puppetmounts://host/modules/my/local/file" - @module = Puppet::Module.new("mymod", "/module/path") - end -end + @module_files_class = Class.new(Puppet::Indirector::ModuleFiles) do + def self.to_s + "Testing::Mytype" + end + end -describe Puppet::Indirector::ModuleFiles, " when finding files" do - include ModuleFilesTerminusTesting + @module_files = @module_files_class.new - it "should strip off the leading '/modules' mount name" do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - @module_files.find(@uri) - end + @uri = "puppetmounts://host/modules/my/local/file" + @module = Puppet::Module.new("mymod", "/module/path") + end - it "should not strip off leading terms that start with '/modules' but are longer words" do - Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil - @module_files.find("puppetmounts://host/modulestart/my/local/file") - end + describe Puppet::Indirector::ModuleFiles, " when finding files" do - it "should search for a module whose name is the first term in the remaining file path" do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - @module_files.find(@uri) - end + it "should strip off the leading '/modules' mount name" do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + @module_files.find(@uri) + end - it "should search for a file relative to the module's files directory" do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file") - @module_files.find(@uri) - end + it "should not strip off leading terms that start with '/modules' but are longer words" do + Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil + @module_files.find("puppetmounts://host/modulestart/my/local/file") + end - it "should return nil if the module does not exist" do - Puppet::Module.expects(:find).with('my', "myenv").returns nil - @module_files.find(@uri).should be_nil - end + it "should search for a module whose name is the first term in the remaining file path" do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + @module_files.find(@uri) + end - it "should return nil if the module exists but the file does not" do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false) - @module_files.find(@uri).should be_nil - end + it "should search for a file relative to the module's files directory" do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file") + @module_files.find(@uri) + end - it "should return an instance of the model if a module is found and the file exists" do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) - @model.expects(:new).returns(:myinstance) - @module_files.find(@uri).should == :myinstance - end + it "should return nil if the module does not exist" do + Puppet::Module.expects(:find).with('my', "myenv").returns nil + @module_files.find(@uri).should be_nil + end - it "should use the node's environment to look up the module if the node name is provided" do - node = stub "node", :environment => "testing" - Puppet::Node.expects(:find).with("mynode").returns(node) - Puppet::Module.expects(:find).with('my', "testing") - @module_files.find(@uri, :node => "mynode") - end + it "should return nil if the module exists but the file does not" do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false) + @module_files.find(@uri).should be_nil + end - it "should use the default environment setting to look up the module if the node name is not provided" do - env = stub "environment", :name => "testing" - Puppet::Node::Environment.stubs(:new).returns(env) - Puppet::Module.expects(:find).with('my', "testing") - @module_files.find(@uri) - end -end + it "should return an instance of the model if a module is found and the file exists" do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) + @model.expects(:new).returns(:myinstance) + @module_files.find(@uri).should == :myinstance + end -describe Puppet::Indirector::ModuleFiles, " when returning instances" do - include ModuleFilesTerminusTesting + it "should use the node's environment to look up the module if the node name is provided" do + node = stub "node", :environment => "testing" + Puppet::Node.expects(:find).with("mynode").returns(node) + Puppet::Module.expects(:find).with('my', "testing") + @module_files.find(@uri, :node => "mynode") + end - before do - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) - @instance = mock 'instance' + it "should use the default environment setting to look up the module if the node name is not provided" do + env = stub "environment", :name => "testing" + Puppet::Node::Environment.stubs(:new).returns(env) + Puppet::Module.expects(:find).with('my', "testing") + @module_files.find(@uri) + end end - it "should create the instance with the key used to find the instance" do - @model.expects(:new).with { |key, *options| key == @uri } - @module_files.find(@uri) - end + describe Puppet::Indirector::ModuleFiles, " when returning instances" do - it "should create the instance with the path at which the instance was found" do - @model.expects(:new).with { |key, options| options[:path] == "/module/path/files/local/file" } - @module_files.find(@uri) - end + before do + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) + @instance = mock 'instance' + end - it "should set the provided :links setting on to the instance if one is provided" do - @model.expects(:new).returns(@instance) - @instance.expects(:links=).with(:mytest) - @module_files.find(@uri, :links => :mytest) - end + it "should create the instance with the key used to find the instance" do + @model.expects(:new).with { |key, *options| key == @uri } + @module_files.find(@uri) + end - it "should not set a :links value if no :links parameter is provided" do - @model.expects(:new).returns(@instance) - @module_files.find(@uri) - end -end + it "should create the instance with the path at which the instance was found" do + @model.expects(:new).with { |key, options| options[:path] == "/module/path/files/local/file" } + @module_files.find(@uri) + end -describe Puppet::Indirector::ModuleFiles, " when authorizing" do - include ModuleFilesTerminusTesting + it "should set the provided :links setting on to the instance if one is provided" do + @model.expects(:new).returns(@instance) + @instance.expects(:links=).with(:mytest) + @module_files.find(@uri, :links => :mytest) + end - before do - @configuration = mock 'configuration' - Puppet::FileServing::Configuration.stubs(:create).returns(@configuration) + it "should not set a :links value if no :links parameter is provided" do + @model.expects(:new).returns(@instance) + @module_files.find(@uri) + end end - it "should have an authorization hook" do - @module_files.should respond_to(:authorized?) - end + describe Puppet::Indirector::ModuleFiles, " when authorizing" do - it "should deny the :destroy method" do - @module_files.authorized?(:destroy, "whatever").should be_false - end + before do + @configuration = mock 'configuration' + Puppet::FileServing::Configuration.stubs(:create).returns(@configuration) + end - it "should deny the :save method" do - @module_files.authorized?(:save, "whatever").should be_false - end + it "should have an authorization hook" do + @module_files.should respond_to(:authorized?) + end - it "should use the file server configuration to determine authorization" do - @configuration.expects(:authorized?) - @module_files.authorized?(:find, "puppetmounts://host/my/file") - end + it "should deny the :destroy method" do + @module_files.authorized?(:destroy, "whatever").should be_false + end - it "should use the path directly from the URI if it already includes /modules" do - @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" } - @module_files.authorized?(:find, "puppetmounts://host/modules/my/file") - end + it "should deny the :save method" do + @module_files.authorized?(:save, "whatever").should be_false + end - it "should add /modules to the file path if it's not included in the URI" do - @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" } - @module_files.authorized?(:find, "puppetmounts://host/my/file") - end + it "should use the file server configuration to determine authorization" do + @configuration.expects(:authorized?) + @module_files.authorized?(:find, "puppetmounts://host/my/file") + end - it "should pass the node name to the file server configuration" do - @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" } - @module_files.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode") - end + it "should use the path directly from the URI if it already includes /modules" do + @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" } + @module_files.authorized?(:find, "puppetmounts://host/modules/my/file") + end - it "should pass the IP address to the file server configuration" do - @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" } - @module_files.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip") - end + it "should add /modules to the file path if it's not included in the URI" do + @configuration.expects(:authorized?).with { |uri, *args| uri == "/modules/my/file" } + @module_files.authorized?(:find, "puppetmounts://host/my/file") + end - it "should return false if the file server configuration denies authorization" do - @configuration.expects(:authorized?).returns(false) - @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_false - end + it "should pass the node name to the file server configuration" do + @configuration.expects(:authorized?).with { |key, options| options[:node] == "mynode" } + @module_files.authorized?(:find, "puppetmounts://host/my/file", :node => "mynode") + end - it "should return true if the file server configuration approves authorization" do - @configuration.expects(:authorized?).returns(true) - @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_true - end -end + it "should pass the IP address to the file server configuration" do + @configuration.expects(:authorized?).with { |key, options| options[:ipaddress] == "myip" } + @module_files.authorized?(:find, "puppetmounts://host/my/file", :ipaddress => "myip") + end -describe Puppet::Indirector::ModuleFiles, " when searching for files" do - include ModuleFilesTerminusTesting + it "should return false if the file server configuration denies authorization" do + @configuration.expects(:authorized?).returns(false) + @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_false + end - it "should strip off the leading '/modules' mount name" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - @module_files.search(@uri) + it "should return true if the file server configuration approves authorization" do + @configuration.expects(:authorized?).returns(true) + @module_files.authorized?(:find, "puppetmounts://host/my/file").should be_true + end end - it "should not strip off leading terms that start with '/modules' but are longer words" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil - @module_files.search("puppetmounts://host/modulestart/my/local/file") - end + describe Puppet::Indirector::ModuleFiles, " when searching for files" do - it "should search for a module whose name is the first term in the remaining file path" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - @module_files.search(@uri) - end + it "should strip off the leading '/modules' mount name" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + @module_files.search(@uri) + end - it "should search for a file relative to the module's files directory" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file") - @module_files.search(@uri) - end + it "should not strip off leading terms that start with '/modules' but are longer words" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('modulestart', "myenv").returns nil + @module_files.search("puppetmounts://host/modulestart/my/local/file") + end - it "should return nil if the module does not exist" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns nil - @module_files.search(@uri).should be_nil - end + it "should search for a module whose name is the first term in the remaining file path" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + @module_files.search(@uri) + end - it "should return nil if the module exists but the file does not" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false) - @module_files.search(@uri).should be_nil - end + it "should search for a file relative to the module's files directory" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file") + @module_files.search(@uri) + end - it "should use the node's environment to look up the module if the node name is provided" do - node = stub "node", :environment => "testing" - Puppet::Node.expects(:find).with("mynode").returns(node) - Puppet::Module.expects(:find).with('my', "testing") - @module_files.search(@uri, :node => "mynode") - end + it "should return nil if the module does not exist" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns nil + @module_files.search(@uri).should be_nil + end - it "should use the default environment setting to look up the module if the node name is not provided and the environment is not set to ''" do - env = stub 'env', :name => "testing" - Puppet::Node::Environment.stubs(:new).returns(env) - Puppet::Module.expects(:find).with('my', "testing") - @module_files.search(@uri) - end + it "should return nil if the module exists but the file does not" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(false) + @module_files.search(@uri).should be_nil + end - it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) - @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", {}) - @module_files.search(@uri) - end + it "should use the node's environment to look up the module if the node name is provided" do + node = stub "node", :environment => "testing" + Puppet::Node.expects(:find).with("mynode").returns(node) + Puppet::Module.expects(:find).with('my', "testing") + @module_files.search(@uri, :node => "mynode") + end - it "should pass any options on to :path2instances" do - Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) - Puppet::Module.expects(:find).with('my', "myenv").returns @module - FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) - @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", :testing => :one, :other => :two) - @module_files.search(@uri, :testing => :one, :other => :two) + it "should use the default environment setting to look up the module if the node name is not provided and the environment is not set to ''" do + env = stub 'env', :name => "testing" + Puppet::Node::Environment.stubs(:new).returns(env) + Puppet::Module.expects(:find).with('my', "testing") + @module_files.search(@uri) + end + + it "should use :path2instances from the terminus_helper to return instances if a module is found and the file exists" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) + @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", {}) + @module_files.search(@uri) + end + + it "should pass any options on to :path2instances" do + Puppet::Node::Environment.stubs(:new).returns(stub('env', :name => "myenv")) + Puppet::Module.expects(:find).with('my', "myenv").returns @module + FileTest.expects(:exists?).with("/module/path/files/local/file").returns(true) + @module_files.expects(:path2instances).with(@uri, "/module/path/files/local/file", :testing => :one, :other => :two) + @module_files.search(@uri, :testing => :one, :other => :two) + end end end diff --git a/spec/unit/indirector/node/ldap.rb b/spec/unit/indirector/node/ldap.rb index 8c6888357..95b73de60 100755 --- a/spec/unit/indirector/node/ldap.rb +++ b/spec/unit/indirector/node/ldap.rb @@ -1,249 +1,247 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/indirector/node/ldap' -module LdapNodeSearching - def setup +describe Puppet::Node::Ldap do + before :each do @searcher = Puppet::Node::Ldap.new @entries = {} entries = @entries @connection = mock 'connection' @entry = mock 'entry' @connection.stubs(:search).yields(@entry) @searcher.stubs(:connection).returns(@connection) @searcher.stubs(:class_attributes).returns([]) @searcher.stubs(:parent_attribute).returns(nil) @searcher.stubs(:search_base).returns(:yay) @searcher.stubs(:search_filter).returns(:filter) @node = mock 'node' @node.stubs(:fact_merge) @name = "mynode" Puppet::Node.stubs(:new).with(@name).returns(@node) end -end -describe Puppet::Node::Ldap, " when searching for nodes" do - include LdapNodeSearching + describe Puppet::Node::Ldap, " when searching for nodes" do - it "should return nil if no results are found in ldap" do - @connection.stubs(:search) - @searcher.find("mynode").should be_nil - end + it "should return nil if no results are found in ldap" do + @connection.stubs(:search) + @searcher.find("mynode").should be_nil + end - it "should return a node object if results are found in ldap" do - @entry.stubs(:to_hash).returns({}) - @searcher.find("mynode").should equal(@node) - end + it "should return a node object if results are found in ldap" do + @entry.stubs(:to_hash).returns({}) + @searcher.find("mynode").should equal(@node) + end - it "should deduplicate class values" do - @entry.stubs(:to_hash).returns({}) - @searcher.stubs(:class_attributes).returns(%w{one two}) - @entry.stubs(:vals).with("one").returns(%w{a b}) - @entry.stubs(:vals).with("two").returns(%w{b c}) - @node.expects(:classes=).with(%w{a b c}) - @searcher.find("mynode") - end + it "should deduplicate class values" do + @entry.stubs(:to_hash).returns({}) + @searcher.stubs(:class_attributes).returns(%w{one two}) + @entry.stubs(:vals).with("one").returns(%w{a b}) + @entry.stubs(:vals).with("two").returns(%w{b c}) + @node.expects(:classes=).with(%w{a b c}) + @searcher.find("mynode") + end - it "should add any values stored in the class_attributes attributes to the node classes" do - @entry.stubs(:to_hash).returns({}) - @searcher.stubs(:class_attributes).returns(%w{one two}) - @entry.stubs(:vals).with("one").returns(%w{a b}) - @entry.stubs(:vals).with("two").returns(%w{c d}) - @node.expects(:classes=).with(%w{a b c d}) - @searcher.find("mynode") - end + it "should add any values stored in the class_attributes attributes to the node classes" do + @entry.stubs(:to_hash).returns({}) + @searcher.stubs(:class_attributes).returns(%w{one two}) + @entry.stubs(:vals).with("one").returns(%w{a b}) + @entry.stubs(:vals).with("two").returns(%w{c d}) + @node.expects(:classes=).with(%w{a b c d}) + @searcher.find("mynode") + end - it "should add all entry attributes as node parameters" do - @entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"]) - @node.expects(:parameters=).with("one" => "two", "three" => "four") - @searcher.find("mynode") - end + it "should add all entry attributes as node parameters" do + @entry.stubs(:to_hash).returns("one" => ["two"], "three" => ["four"]) + @node.expects(:parameters=).with("one" => "two", "three" => "four") + @searcher.find("mynode") + end - it "should retain false parameter values" do - @entry.stubs(:to_hash).returns("one" => [false]) - @node.expects(:parameters=).with("one" => false) - @searcher.find("mynode") - end + it "should retain false parameter values" do + @entry.stubs(:to_hash).returns("one" => [false]) + @node.expects(:parameters=).with("one" => false) + @searcher.find("mynode") + end - it "should turn single-value parameter value arrays into single non-arrays" do - @entry.stubs(:to_hash).returns("one" => ["a"]) - @node.expects(:parameters=).with("one" => "a") - @searcher.find("mynode") - end + it "should turn single-value parameter value arrays into single non-arrays" do + @entry.stubs(:to_hash).returns("one" => ["a"]) + @node.expects(:parameters=).with("one" => "a") + @searcher.find("mynode") + end - it "should keep multi-valued parametes as arrays" do - @entry.stubs(:to_hash).returns("one" => ["a", "b"]) - @node.expects(:parameters=).with("one" => ["a", "b"]) - @searcher.find("mynode") + it "should keep multi-valued parametes as arrays" do + @entry.stubs(:to_hash).returns("one" => ["a", "b"]) + @node.expects(:parameters=).with("one" => ["a", "b"]) + @searcher.find("mynode") + end end -end -describe Puppet::Node::Ldap, " when a parent node is specified" do - include LdapNodeSearching + describe Puppet::Node::Ldap, " when a parent node is specified" do - before do - @parent = mock 'parent' - @parent_parent = mock 'parent_parent' + before do + @parent = mock 'parent' + @parent_parent = mock 'parent_parent' - @searcher.meta_def(:search_filter) do |name| - return name - end - @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry) - @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent) - @connection.stubs(:search).with { |*args| args[2] == 'parent_parent' }.yields(@parent_parent) + @searcher.meta_def(:search_filter) do |name| + return name + end + @connection.stubs(:search).with { |*args| args[2] == @name }.yields(@entry) + @connection.stubs(:search).with { |*args| args[2] == 'parent' }.yields(@parent) + @connection.stubs(:search).with { |*args| args[2] == 'parent_parent' }.yields(@parent_parent) - @searcher.stubs(:parent_attribute).returns(:parent) - end + @searcher.stubs(:parent_attribute).returns(:parent) + end - it "should fail if the parent cannot be found" do - @connection.stubs(:search).with { |*args| args[2] == 'parent' }.returns("whatever") + it "should fail if the parent cannot be found" do + @connection.stubs(:search).with { |*args| args[2] == 'parent' }.returns("whatever") - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + @entry.stubs(:to_hash).returns({}) + @entry.stubs(:vals).with(:parent).returns(%w{parent}) - proc { @searcher.find("mynode") }.should raise_error(Puppet::Error) - end + proc { @searcher.find("mynode") }.should raise_error(Puppet::Error) + end - it "should add any parent classes to the node's classes" do - @entry.stubs(:to_hash).returns({}) - @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @entry.stubs(:vals).with("classes").returns(%w{a b}) + it "should add any parent classes to the node's classes" do + @entry.stubs(:to_hash).returns({}) + @entry.stubs(:vals).with(:parent).returns(%w{parent}) + @entry.stubs(:vals).with("classes").returns(%w{a b}) - @parent.stubs(:to_hash).returns({}) - @parent.stubs(:vals).with("classes").returns(%w{c d}) - @parent.stubs(:vals).with(:parent).returns(nil) + @parent.stubs(:to_hash).returns({}) + @parent.stubs(:vals).with("classes").returns(%w{c d}) + @parent.stubs(:vals).with(:parent).returns(nil) - @searcher.stubs(:class_attributes).returns(%w{classes}) - @node.expects(:classes=).with(%w{a b c d}) - @searcher.find("mynode") - end + @searcher.stubs(:class_attributes).returns(%w{classes}) + @node.expects(:classes=).with(%w{a b c d}) + @searcher.find("mynode") + end - it "should add any parent parameters to the node's parameters" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should add any parent parameters to the node's parameters" do + @entry.stubs(:to_hash).returns("one" => "two") + @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns(nil) + @parent.stubs(:to_hash).returns("three" => "four") + @parent.stubs(:vals).with(:parent).returns(nil) - @node.expects(:parameters=).with("one" => "two", "three" => "four") - @searcher.find("mynode") - end + @node.expects(:parameters=).with("one" => "two", "three" => "four") + @searcher.find("mynode") + end - it "should prefer node parameters over parent parameters" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should prefer node parameters over parent parameters" do + @entry.stubs(:to_hash).returns("one" => "two") + @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @parent.stubs(:to_hash).returns("one" => "three") - @parent.stubs(:vals).with(:parent).returns(nil) + @parent.stubs(:to_hash).returns("one" => "three") + @parent.stubs(:vals).with(:parent).returns(nil) - @node.expects(:parameters=).with("one" => "two") - @searcher.find("mynode") - end + @node.expects(:parameters=).with("one" => "two") + @searcher.find("mynode") + end - it "should recursively look up parent information" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should recursively look up parent information" do + @entry.stubs(:to_hash).returns("one" => "two") + @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns(['parent_parent']) + @parent.stubs(:to_hash).returns("three" => "four") + @parent.stubs(:vals).with(:parent).returns(['parent_parent']) - @parent_parent.stubs(:to_hash).returns("five" => "six") - @parent_parent.stubs(:vals).with(:parent).returns(nil) - @parent_parent.stubs(:vals).with(:parent).returns(nil) + @parent_parent.stubs(:to_hash).returns("five" => "six") + @parent_parent.stubs(:vals).with(:parent).returns(nil) + @parent_parent.stubs(:vals).with(:parent).returns(nil) - @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six") - @searcher.find("mynode") - end + @node.expects(:parameters=).with("one" => "two", "three" => "four", "five" => "six") + @searcher.find("mynode") + end - it "should not allow loops in parent declarations" do - @entry.stubs(:to_hash).returns("one" => "two") - @entry.stubs(:vals).with(:parent).returns(%w{parent}) + it "should not allow loops in parent declarations" do + @entry.stubs(:to_hash).returns("one" => "two") + @entry.stubs(:vals).with(:parent).returns(%w{parent}) - @parent.stubs(:to_hash).returns("three" => "four") - @parent.stubs(:vals).with(:parent).returns([@name]) - proc { @searcher.find("mynode") }.should raise_error(ArgumentError) + @parent.stubs(:to_hash).returns("three" => "four") + @parent.stubs(:vals).with(:parent).returns([@name]) + proc { @searcher.find("mynode") }.should raise_error(ArgumentError) + end end end describe Puppet::Node::Ldap, " when developing the search query" do before do @searcher = Puppet::Node::Ldap.new end it "should return the value of the :ldapclassattrs split on commas as the class attributes" do Puppet.stubs(:[]).with(:ldapclassattrs).returns("one,two") @searcher.class_attributes.should == %w{one two} end it "should return nil as the parent attribute if the :ldapparentattr is set to an empty string" do Puppet.stubs(:[]).with(:ldapparentattr).returns("") @searcher.parent_attribute.should be_nil end it "should return the value of the :ldapparentattr as the parent attribute" do Puppet.stubs(:[]).with(:ldapparentattr).returns("pere") @searcher.parent_attribute.should == "pere" end it "should use the value of the :ldapstring as the search filter" do Puppet.stubs(:[]).with(:ldapstring).returns("mystring") @searcher.search_filter("testing").should == "mystring" end it "should replace '%s' with the node name in the search filter if it is present" do Puppet.stubs(:[]).with(:ldapstring).returns("my%sstring") @searcher.search_filter("testing").should == "mytestingstring" end it "should not modify the global :ldapstring when replacing '%s' in the search filter" do filter = mock 'filter' filter.expects(:include?).with("%s").returns(true) filter.expects(:gsub).with("%s", "testing").returns("mynewstring") Puppet.stubs(:[]).with(:ldapstring).returns(filter) @searcher.search_filter("testing").should == "mynewstring" end end describe Puppet::Node::Ldap, " when deciding attributes to search for" do before do @searcher = Puppet::Node::Ldap.new end it "should use 'nil' if the :ldapattrs setting is 'all'" do Puppet.stubs(:[]).with(:ldapattrs).returns("all") @searcher.search_attributes.should be_nil end it "should split the value of :ldapattrs on commas and use the result as the attribute list" do Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") @searcher.stubs(:class_attributes).returns([]) @searcher.stubs(:parent_attribute).returns(nil) @searcher.search_attributes.should == %w{one two} end it "should add the class attributes to the search attributes if not returning all attributes" do Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") @searcher.stubs(:class_attributes).returns(%w{three four}) @searcher.stubs(:parent_attribute).returns(nil) # Sort them so i don't have to care about return order @searcher.search_attributes.sort.should == %w{one two three four}.sort end it "should add the parent attribute to the search attributes if not returning all attributes" do Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") @searcher.stubs(:class_attributes).returns([]) @searcher.stubs(:parent_attribute).returns("parent") @searcher.search_attributes.sort.should == %w{one two parent}.sort end it "should not add nil parent attributes to the search attributes" do Puppet.stubs(:[]).with(:ldapattrs).returns("one,two") @searcher.stubs(:class_attributes).returns([]) @searcher.stubs(:parent_attribute).returns(nil) @searcher.search_attributes.should == %w{one two} end end diff --git a/spec/unit/indirector/terminus.rb b/spec/unit/indirector/terminus.rb index 99193dbc3..86813e4e5 100755 --- a/spec/unit/indirector/terminus.rb +++ b/spec/unit/indirector/terminus.rb @@ -1,302 +1,299 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/defaults' require 'puppet/indirector' require 'puppet/indirector/file' -module TerminusInstanceTesting - def setup +describe Puppet::Indirector::Terminus do + before :each do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @indirection = stub 'indirection', :name => :my_stuff, :register_terminus_type => nil Puppet::Indirector::Indirection.stubs(:instance).with(:my_stuff).returns(@indirection) @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do def self.to_s "Testing::Abstract" end end @terminus_class = Class.new(@abstract_terminus) do def self.to_s "MyStuff::TermType" end end @terminus = @terminus_class.new end -end -describe Puppet::Indirector::Terminus do - include TerminusInstanceTesting + describe Puppet::Indirector::Terminus do - it "should provide a method for setting terminus class documentation" do - @terminus_class.should respond_to(:desc) - end + it "should provide a method for setting terminus class documentation" do + @terminus_class.should respond_to(:desc) + end - it "should support a class-level name attribute" do - @terminus_class.should respond_to(:name) - end + it "should support a class-level name attribute" do + @terminus_class.should respond_to(:name) + end - it "should support a class-level indirection attribute" do - @terminus_class.should respond_to(:indirection) - end + it "should support a class-level indirection attribute" do + @terminus_class.should respond_to(:indirection) + end - it "should support a class-level terminus-type attribute" do - @terminus_class.should respond_to(:terminus_type) - end + it "should support a class-level terminus-type attribute" do + @terminus_class.should respond_to(:terminus_type) + end - it "should support a class-level model attribute" do - @terminus_class.should respond_to(:model) + it "should support a class-level model attribute" do + @terminus_class.should respond_to(:model) + end + + it "should accept indirection instances as its indirection" do + indirection = stub 'indirection', :is_a? => true, :register_terminus_type => nil + proc { @terminus_class.indirection = indirection }.should_not raise_error + @terminus_class.indirection.should equal(indirection) + end + + it "should look up indirection instances when only a name has been provided" do + indirection = mock 'indirection' + Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(indirection) + @terminus_class.indirection = :myind + @terminus_class.indirection.should equal(indirection) + end + + it "should fail when provided a name that does not resolve to an indirection" do + Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(nil) + proc { @terminus_class.indirection = :myind }.should raise_error(ArgumentError) + + # It shouldn't overwrite our existing one (or, more normally, it shouldn't set + # anything). + @terminus_class.indirection.should equal(@indirection) + end end - it "should accept indirection instances as its indirection" do - indirection = stub 'indirection', :is_a? => true, :register_terminus_type => nil - proc { @terminus_class.indirection = indirection }.should_not raise_error - @terminus_class.indirection.should equal(indirection) + describe Puppet::Indirector::Terminus, " when creating terminus classes" do + it "should associate the subclass with an indirection based on the subclass constant" do + @terminus.indirection.should equal(@indirection) + end + + it "should set the subclass's type to the abstract terminus name" do + @terminus.terminus_type.should == :abstract + end + + it "should set the subclass's name to the indirection name" do + @terminus.name.should == :term_type + end + + it "should set the subclass's model to the indirection model" do + @indirection.expects(:model).returns :yay + @terminus.model.should == :yay + end end - it "should look up indirection instances when only a name has been provided" do - indirection = mock 'indirection' - Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(indirection) - @terminus_class.indirection = :myind - @terminus_class.indirection.should equal(indirection) + describe Puppet::Indirector::Terminus, " when a terminus instance" do + + it "should return the class's name as its name" do + @terminus.name.should == :term_type + end + + it "should return the class's indirection as its indirection" do + @terminus.indirection.should equal(@indirection) + end + + it "should set the instances's type to the abstract terminus type's name" do + @terminus.terminus_type.should == :abstract + end + + it "should set the instances's model to the indirection's model" do + @indirection.expects(:model).returns :yay + @terminus.model.should == :yay + end end - it "should fail when provided a name that does not resolve to an indirection" do - Puppet::Indirector::Indirection.expects(:instance).with(:myind).returns(nil) - proc { @terminus_class.indirection = :myind }.should raise_error(ArgumentError) + describe Puppet::Indirector::Terminus, " when managing indirected instances" do + + it "should support comparing an instance's version with the terminus's version using just the instance's key" do + @terminus.should respond_to(:has_most_recent?) + end + + it "should fail if the :version method has not been overridden and no :find method is available" do + proc { @terminus.version('yay') }.should raise_error(Puppet::DevError) + end + + it "should use a found instance's version by default" do + name = 'instance' + instance = stub name, :version => 2 + @terminus.expects(:find).with(name).returns(instance) + @terminus.version(name).should == 2 + end - # It shouldn't overwrite our existing one (or, more normally, it shouldn't set - # anything). - @terminus_class.indirection.should equal(@indirection) + it "should return nil as the version if no instance can be found" do + name = 'instance' + @terminus.expects(:find).with(name).returns(nil) + @terminus.version(name).should be_nil + end + + it "should consider an instance fresh if its version is more recent than the version provided" do + name = "yay" + @terminus.expects(:version).with(name).returns(5) + @terminus.has_most_recent?(name, 4).should be_true + end + + it "should consider an instance fresh if its version is equal to the version provided" do + name = "yay" + @terminus.expects(:version).with(name).returns(5) + @terminus.has_most_recent?(name, 5).should be_true + end + + it "should consider an instance not fresh if the provided version is more recent than its version" do + name = "yay" + @terminus.expects(:version).with(name).returns(4) + @terminus.has_most_recent?(name, 5).should be_false + end + + # Times annoyingly can't be compared directly to numbers, and our + # default version is 0. + it "should convert versions to floats when checking for freshness" do + existing = mock 'existing version' + new = mock 'new version' + existing.expects(:to_f).returns(1.0) + new.expects(:to_f).returns(1.0) + name = "yay" + @terminus.expects(:version).with(name).returns(existing) + @terminus.has_most_recent?(name, new) + end end end # LAK: This could reasonably be in the Indirection instances, too. It doesn't make # a whole heckuva lot of difference, except that with the instance loading in # the Terminus base class, we have to have a check to see if we're already # instance-loading a given terminus class type. describe Puppet::Indirector::Terminus, " when managing terminus classes" do it "should provide a method for registering terminus classes" do Puppet::Indirector::Terminus.should respond_to(:register_terminus_class) end it "should provide a method for returning terminus classes by name and type" do terminus = stub 'terminus_type', :name => :abstract, :indirection_name => :whatever Puppet::Indirector::Terminus.register_terminus_class(terminus) Puppet::Indirector::Terminus.terminus_class(:whatever, :abstract).should equal(terminus) end it "should set up autoloading for any terminus class types requested" do Puppet::Indirector::Terminus.expects(:instance_load).with(:test2, "puppet/indirector/test2") Puppet::Indirector::Terminus.terminus_class(:test2, :whatever) end it "should load terminus classes that are not found" do # Set up instance loading; it would normally happen automatically Puppet::Indirector::Terminus.instance_load :test1, "puppet/indirector/test1" Puppet::Indirector::Terminus.instance_loader(:test1).expects(:load).with(:yay) Puppet::Indirector::Terminus.terminus_class(:test1, :yay) end it "should fail when no indirection can be found" do Puppet::Indirector::Indirection.expects(:instance).with(:my_indirection).returns(nil) @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do def self.to_s "Abstract" end end proc { @terminus = Class.new(@abstract_terminus) do def self.to_s "MyIndirection::TestType" end end }.should raise_error(ArgumentError) end it "should register the terminus class with the terminus base class" do Puppet::Indirector::Terminus.expects(:register_terminus_class).with do |type| type.indirection_name == :my_indirection and type.name == :test_terminus end @indirection = stub 'indirection', :name => :my_indirection, :register_terminus_type => nil Puppet::Indirector::Indirection.expects(:instance).with(:my_indirection).returns(@indirection) @abstract_terminus = Class.new(Puppet::Indirector::Terminus) do def self.to_s "Abstract" end end @terminus = Class.new(@abstract_terminus) do def self.to_s "MyIndirection::TestTerminus" end end end end describe Puppet::Indirector::Terminus, " when parsing class constants for indirection and terminus names" do before do @subclass = mock 'subclass' @subclass.stubs(:to_s).returns("TestInd::OneTwo") @subclass.stubs(:mark_as_abstract_terminus) Puppet::Indirector::Terminus.stubs(:register_terminus_class) end it "should fail when anonymous classes are used" do proc { Puppet::Indirector::Terminus.inherited(Class.new) }.should raise_error(Puppet::DevError) end it "should use the last term in the constant for the terminus class name" do @subclass.expects(:name=).with(:one_two) @subclass.stubs(:indirection=) Puppet::Indirector::Terminus.inherited(@subclass) end it "should convert the terminus name to a downcased symbol" do @subclass.expects(:name=).with(:one_two) @subclass.stubs(:indirection=) Puppet::Indirector::Terminus.inherited(@subclass) end it "should use the second to last term in the constant for the indirection name" do @subclass.expects(:indirection=).with(:test_ind) @subclass.stubs(:name=) @subclass.stubs(:terminus_type=) Puppet::Indirector::File.inherited(@subclass) end it "should convert the indirection name to a downcased symbol" do @subclass.expects(:indirection=).with(:test_ind) @subclass.stubs(:name=) @subclass.stubs(:terminus_type=) Puppet::Indirector::File.inherited(@subclass) end it "should convert camel case to lower case with underscores as word separators" do @subclass.expects(:name=).with(:one_two) @subclass.stubs(:indirection=) Puppet::Indirector::Terminus.inherited(@subclass) end end describe Puppet::Indirector::Terminus, " when creating terminus class types" do before do Puppet::Indirector::Terminus.stubs(:register_terminus_class) @subclass = Class.new(Puppet::Indirector::Terminus) do def self.to_s "Puppet::Indirector::Terminus::MyTermType" end end end it "should set the name of the abstract subclass to be its class constant" do @subclass.name.should equal(:my_term_type) end it "should mark abstract terminus types as such" do @subclass.should be_abstract_terminus end it "should not allow instances of abstract subclasses to be created" do proc { @subclass.new }.should raise_error(Puppet::DevError) end end -describe Puppet::Indirector::Terminus, " when creating terminus classes" do - include TerminusInstanceTesting - it "should associate the subclass with an indirection based on the subclass constant" do - @terminus.indirection.should equal(@indirection) - end - - it "should set the subclass's type to the abstract terminus name" do - @terminus.terminus_type.should == :abstract - end - - it "should set the subclass's name to the indirection name" do - @terminus.name.should == :term_type - end - - it "should set the subclass's model to the indirection model" do - @indirection.expects(:model).returns :yay - @terminus.model.should == :yay - end -end - -describe Puppet::Indirector::Terminus, " when a terminus instance" do - include TerminusInstanceTesting - - it "should return the class's name as its name" do - @terminus.name.should == :term_type - end - - it "should return the class's indirection as its indirection" do - @terminus.indirection.should equal(@indirection) - end - - it "should set the instances's type to the abstract terminus type's name" do - @terminus.terminus_type.should == :abstract - end - - it "should set the instances's model to the indirection's model" do - @indirection.expects(:model).returns :yay - @terminus.model.should == :yay - end -end - -describe Puppet::Indirector::Terminus, " when managing indirected instances" do - include TerminusInstanceTesting - - it "should support comparing an instance's version with the terminus's version using just the instance's key" do - @terminus.should respond_to(:has_most_recent?) - end - - it "should fail if the :version method has not been overridden and no :find method is available" do - proc { @terminus.version('yay') }.should raise_error(Puppet::DevError) - end - - it "should use a found instance's version by default" do - name = 'instance' - instance = stub name, :version => 2 - @terminus.expects(:find).with(name).returns(instance) - @terminus.version(name).should == 2 - end - - it "should return nil as the version if no instance can be found" do - name = 'instance' - @terminus.expects(:find).with(name).returns(nil) - @terminus.version(name).should be_nil - end - - it "should consider an instance fresh if its version is more recent than the version provided" do - name = "yay" - @terminus.expects(:version).with(name).returns(5) - @terminus.has_most_recent?(name, 4).should be_true - end - - it "should consider an instance fresh if its version is equal to the version provided" do - name = "yay" - @terminus.expects(:version).with(name).returns(5) - @terminus.has_most_recent?(name, 5).should be_true - end - - it "should consider an instance not fresh if the provided version is more recent than its version" do - name = "yay" - @terminus.expects(:version).with(name).returns(4) - @terminus.has_most_recent?(name, 5).should be_false - end - - # Times annoyingly can't be compared directly to numbers, and our - # default version is 0. - it "should convert versions to floats when checking for freshness" do - existing = mock 'existing version' - new = mock 'new version' - existing.expects(:to_f).returns(1.0) - new.expects(:to_f).returns(1.0) - name = "yay" - @terminus.expects(:version).with(name).returns(existing) - @terminus.has_most_recent?(name, new) - end -end diff --git a/spec/unit/indirector/yaml.rb b/spec/unit/indirector/yaml.rb index f217a31b5..2e0b453d7 100755 --- a/spec/unit/indirector/yaml.rb +++ b/spec/unit/indirector/yaml.rb @@ -1,104 +1,101 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/indirector/yaml' -module YamlTesting - def setup +describe Puppet::Indirector::Yaml, " when choosing file location" do + before :each do @indirection = stub 'indirection', :name => :my_yaml, :register_terminus_type => nil Puppet::Indirector::Indirection.stubs(:instance).with(:my_yaml).returns(@indirection) @store_class = Class.new(Puppet::Indirector::Yaml) do def self.to_s "MyYaml::MyType" end end @store = @store_class.new @subject = Object.new @subject.metaclass.send(:attr_accessor, :name) @subject.name = :me @dir = "/what/ever" Puppet.settings.stubs(:use) Puppet.settings.stubs(:value).with(:yamldir).returns(@dir) end -end -describe Puppet::Indirector::Yaml, " when choosing file location" do - include YamlTesting + describe Puppet::Indirector::Yaml, " when choosing file location" do - it "should store all files in a single file root set in the Puppet defaults" do - @store.send(:path, :me).should =~ %r{^#{@dir}} - end + it "should store all files in a single file root set in the Puppet defaults" do + @store.send(:path, :me).should =~ %r{^#{@dir}} + end - it "should use the terminus name for choosing the subdirectory" do - @store.send(:path, :me).should =~ %r{^#{@dir}/my_yaml} - end + it "should use the terminus name for choosing the subdirectory" do + @store.send(:path, :me).should =~ %r{^#{@dir}/my_yaml} + end - it "should use the object's name to determine the file name" do - @store.send(:path, :me).should =~ %r{me.yaml$} + it "should use the object's name to determine the file name" do + @store.send(:path, :me).should =~ %r{me.yaml$} + end end -end -describe Puppet::Indirector::Yaml, " when storing objects as YAML" do - include YamlTesting + describe Puppet::Indirector::Yaml, " when storing objects as YAML" do - it "should only store objects that respond to :name" do - proc { @store.save(Object.new) }.should raise_error(ArgumentError) - end + it "should only store objects that respond to :name" do + proc { @store.save(Object.new) }.should raise_error(ArgumentError) + end - it "should convert Ruby objects to YAML and write them to disk" do - yaml = @subject.to_yaml - file = mock 'file' - path = @store.send(:path, @subject.name) - FileTest.expects(:exist?).with(File.dirname(path)).returns(true) - File.expects(:open).with(path, "w", 0660).yields(file) - file.expects(:print).with(yaml) + it "should convert Ruby objects to YAML and write them to disk" do + yaml = @subject.to_yaml + file = mock 'file' + path = @store.send(:path, @subject.name) + FileTest.expects(:exist?).with(File.dirname(path)).returns(true) + File.expects(:open).with(path, "w", 0660).yields(file) + file.expects(:print).with(yaml) - @store.save(@subject) - end + @store.save(@subject) + end - it "should create the indirection subdirectory if it does not exist" do - yaml = @subject.to_yaml - file = mock 'file' - path = @store.send(:path, @subject.name) - dir = File.dirname(path) - FileTest.expects(:exist?).with(dir).returns(false) - Dir.expects(:mkdir).with(dir) - File.expects(:open).with(path, "w", 0660).yields(file) - file.expects(:print).with(yaml) - - @store.save(@subject) + it "should create the indirection subdirectory if it does not exist" do + yaml = @subject.to_yaml + file = mock 'file' + path = @store.send(:path, @subject.name) + dir = File.dirname(path) + FileTest.expects(:exist?).with(dir).returns(false) + Dir.expects(:mkdir).with(dir) + File.expects(:open).with(path, "w", 0660).yields(file) + file.expects(:print).with(yaml) + + @store.save(@subject) + end end -end -describe Puppet::Indirector::Yaml, " when retrieving YAML" do - include YamlTesting + describe Puppet::Indirector::Yaml, " when retrieving YAML" do - it "should require the name of the object to retrieve" do - proc { @store.find(nil) }.should raise_error(ArgumentError) - end + it "should require the name of the object to retrieve" do + proc { @store.find(nil) }.should raise_error(ArgumentError) + end - it "should read YAML in from disk and convert it to Ruby objects" do - path = @store.send(:path, @subject.name) + it "should read YAML in from disk and convert it to Ruby objects" do + path = @store.send(:path, @subject.name) - yaml = @subject.to_yaml - FileTest.expects(:exist?).with(path).returns(true) - File.expects(:read).with(path).returns(yaml) + yaml = @subject.to_yaml + FileTest.expects(:exist?).with(path).returns(true) + File.expects(:read).with(path).returns(yaml) - @store.find(@subject.name).instance_variable_get("@name").should == :me - end + @store.find(@subject.name).instance_variable_get("@name").should == :me + end - it "should fail coherently when the stored YAML is invalid" do - path = @store.send(:path, @subject.name) + it "should fail coherently when the stored YAML is invalid" do + path = @store.send(:path, @subject.name) - # Something that will fail in yaml - yaml = "--- !ruby/object:Hash" + # Something that will fail in yaml + yaml = "--- !ruby/object:Hash" - FileTest.expects(:exist?).with(path).returns(true) - File.expects(:read).with(path).returns(yaml) + FileTest.expects(:exist?).with(path).returns(true) + File.expects(:read).with(path).returns(yaml) - proc { @store.find(@subject.name) }.should raise_error(Puppet::Error) + proc { @store.find(@subject.name) }.should raise_error(Puppet::Error) + end end -end +end \ No newline at end of file diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb index be4edb65d..ecbd20487 100755 --- a/spec/unit/node/catalog.rb +++ b/spec/unit/node/catalog.rb @@ -1,816 +1,813 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' describe Puppet::Node::Catalog, " when compiling" do it "should accept tags" do config = Puppet::Node::Catalog.new("mynode") config.tag("one") config.tags.should == %w{one} end it "should accept multiple tags at once" do config = Puppet::Node::Catalog.new("mynode") config.tag("one", "two") config.tags.should == %w{one two} end it "should convert all tags to strings" do config = Puppet::Node::Catalog.new("mynode") config.tag("one", :two) config.tags.should == %w{one two} end it "should tag with both the qualified name and the split name" do config = Puppet::Node::Catalog.new("mynode") config.tag("one::two") config.tags.include?("one").should be_true config.tags.include?("one::two").should be_true end it "should accept classes" do config = Puppet::Node::Catalog.new("mynode") config.add_class("one") config.classes.should == %w{one} config.add_class("two", "three") config.classes.should == %w{one two three} end it "should tag itself with passed class names" do config = Puppet::Node::Catalog.new("mynode") config.add_class("one") config.tags.should == %w{one} end end describe Puppet::Node::Catalog, " when extracting" do it "should return extraction result as the method result" do config = Puppet::Node::Catalog.new("mynode") config.expects(:extraction_format).returns(:whatever) config.expects(:extract_to_whatever).returns(:result) config.extract.should == :result end end describe Puppet::Node::Catalog, " when extracting transobjects" do def mkscope @parser = Puppet::Parser::Parser.new :Code => "" @node = Puppet::Node.new("mynode") @compiler = Puppet::Parser::Compiler.new(@node, @parser) # XXX This is ridiculous. @compiler.send(:evaluate_main) @scope = @compiler.topscope end def mkresource(type, name) Puppet::Parser::Resource.new(:type => type, :title => name, :source => @source, :scope => @scope) end it "should always create a TransBucket for the 'main' class" do config = Puppet::Node::Catalog.new("mynode") @scope = mkscope @source = mock 'source' main = mkresource("class", :main) config.add_vertex(main) bucket = mock 'bucket' bucket.expects(:classes=).with(config.classes) main.stubs(:builtin?).returns(false) main.expects(:to_transbucket).returns(bucket) config.extract_to_transportable.should equal(bucket) end # This isn't really a spec-style test, but I don't know how better to do it. it "should transform the resource graph into a tree of TransBuckets and TransObjects" do config = Puppet::Node::Catalog.new("mynode") @scope = mkscope @source = mock 'source' defined = mkresource("class", :main) builtin = mkresource("file", "/yay") config.add_edge(defined, builtin) bucket = [] bucket.expects(:classes=).with(config.classes) defined.stubs(:builtin?).returns(false) defined.expects(:to_transbucket).returns(bucket) builtin.expects(:to_transobject).returns(:builtin) config.extract_to_transportable.should == [:builtin] end # Now try it with a more complicated graph -- a three tier graph, each tier it "should transform arbitrarily deep graphs into isomorphic trees" do config = Puppet::Node::Catalog.new("mynode") @scope = mkscope @scope.stubs(:tags).returns([]) @source = mock 'source' # Create our scopes. top = mkresource "class", :main topbucket = [] topbucket.expects(:classes=).with([]) top.expects(:to_trans).returns(topbucket) topres = mkresource "file", "/top" topres.expects(:to_trans).returns(:topres) config.add_edge top, topres middle = mkresource "class", "middle" middle.expects(:to_trans).returns([]) config.add_edge top, middle midres = mkresource "file", "/mid" midres.expects(:to_trans).returns(:midres) config.add_edge middle, midres bottom = mkresource "class", "bottom" bottom.expects(:to_trans).returns([]) config.add_edge middle, bottom botres = mkresource "file", "/bot" botres.expects(:to_trans).returns(:botres) config.add_edge bottom, botres toparray = config.extract_to_transportable # This is annoying; it should look like: # [[[:botres], :midres], :topres] # but we can't guarantee sort order. toparray.include?(:topres).should be_true midarray = toparray.find { |t| t.is_a?(Array) } midarray.include?(:midres).should be_true botarray = midarray.find { |t| t.is_a?(Array) } botarray.include?(:botres).should be_true end end describe Puppet::Node::Catalog, " when converting to a transobject catalog" do class TestResource attr_accessor :name, :virtual, :builtin def initialize(name, options = {}) @name = name options.each { |p,v| send(p.to_s + "=", v) } end def ref if builtin? "File[%s]" % name else "Class[%s]" % name end end def virtual? virtual end def builtin? builtin end def to_transobject Puppet::TransObject.new(name, builtin? ? "file" : "class") end end before do @original = Puppet::Node::Catalog.new("mynode") @original.tag(*%w{one two three}) @original.add_class *%w{four five six} @top = TestResource.new 'top' @topobject = TestResource.new 'topobject', :builtin => true @virtual = TestResource.new 'virtual', :virtual => true @virtualobject = TestResource.new 'virtualobject', :builtin => true, :virtual => true @middle = TestResource.new 'middle' @middleobject = TestResource.new 'middleobject', :builtin => true @bottom = TestResource.new 'bottom' @bottomobject = TestResource.new 'bottomobject', :builtin => true @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] @original.add_edge(@top, @topobject) @original.add_edge(@top, @virtual) @original.add_edge(@virtual, @virtualobject) @original.add_edge(@top, @middle) @original.add_edge(@middle, @middleobject) @original.add_edge(@middle, @bottom) @original.add_edge(@bottom, @bottomobject) @catalog = @original.to_transportable end it "should add all resources as TransObjects" do @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::TransObject) } end it "should not extract defined virtual resources" do @catalog.vertices.find { |v| v.name == "virtual" }.should be_nil end it "should not extract builtin virtual resources" do @catalog.vertices.find { |v| v.name == "virtualobject" }.should be_nil end it "should copy the tag list to the new catalog" do @catalog.tags.sort.should == @original.tags.sort end it "should copy the class list to the new catalog" do @catalog.classes.should == @original.classes end it "should duplicate the original edges" do @original.edges.each do |edge| next if edge.source.virtual? or edge.target.virtual? source = @catalog.resource(edge.source.ref) target = @catalog.resource(edge.target.ref) source.should_not be_nil target.should_not be_nil @catalog.edge?(source, target).should be_true end end it "should set itself as the catalog for each converted resource" do @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } end end describe Puppet::Node::Catalog, " when converting to a RAL catalog" do before do @original = Puppet::Node::Catalog.new("mynode") @original.tag(*%w{one two three}) @original.add_class *%w{four five six} @top = Puppet::TransObject.new 'top', "class" @topobject = Puppet::TransObject.new '/topobject', "file" @middle = Puppet::TransObject.new 'middle', "class" @middleobject = Puppet::TransObject.new '/middleobject', "file" @bottom = Puppet::TransObject.new 'bottom', "class" @bottomobject = Puppet::TransObject.new '/bottomobject', "file" @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] @original.add_resource(*@resources) @original.add_edge(@top, @topobject) @original.add_edge(@top, @middle) @original.add_edge(@middle, @middleobject) @original.add_edge(@middle, @bottom) @original.add_edge(@bottom, @bottomobject) @catalog = @original.to_ral end it "should add all resources as RAL instances" do @resources.each { |resource| @catalog.resource(resource.ref).should be_instance_of(Puppet::Type) } end it "should copy the tag list to the new catalog" do @catalog.tags.sort.should == @original.tags.sort end it "should copy the class list to the new catalog" do @catalog.classes.should == @original.classes end it "should duplicate the original edges" do @original.edges.each do |edge| @catalog.edge?(@catalog.resource(edge.source.ref), @catalog.resource(edge.target.ref)).should be_true end end it "should set itself as the catalog for each converted resource" do @catalog.vertices.each { |v| v.catalog.object_id.should equal(@catalog.object_id) } end # This tests #931. it "should not lose track of resources whose names vary" do changer = Puppet::TransObject.new 'changer', 'test' config = Puppet::Node::Catalog.new('test') config.add_resource(changer) config.add_resource(@top) config.add_edge(@top, changer) resource = stub 'resource', :name => "changer2", :title => "changer2", :ref => "Test[changer2]", :catalog= => nil, :remove => nil changer.expects(:to_type).returns(resource) newconfig = nil Puppet::Type.allclear proc { @catalog = config.to_ral }.should_not raise_error @catalog.resource("Test[changer2]").should equal(resource) end after do # Remove all resource instances. @catalog.clear(true) end end describe Puppet::Node::Catalog, " when functioning as a resource container" do before do @catalog = Puppet::Node::Catalog.new("host") @one = stub 'resource1', :ref => "Me[one]", :catalog= => nil @two = stub 'resource2', :ref => "Me[two]", :catalog= => nil @dupe = stub 'resource3', :ref => "Me[one]", :catalog= => nil end it "should provide a method to add one or more resources" do @catalog.add_resource @one, @two @catalog.resource(@one.ref).should equal(@one) @catalog.resource(@two.ref).should equal(@two) end it "should set itself as the resource's catalog if it is not a relationship graph" do @one.expects(:catalog=).with(@catalog) @catalog.add_resource @one end it "should not set itself as the resource's catalog if it is a relationship graph" do @one.expects(:catalog=).never @catalog.is_relationship_graph = true @catalog.add_resource @one end it "should make all vertices available by resource reference" do @catalog.add_resource(@one) @catalog.resource(@one.ref).should equal(@one) @catalog.vertices.find { |r| r.ref == @one.ref }.should equal(@one) end it "should canonize how resources are referred to during retrieval when both type and title are provided" do @catalog.add_resource(@one) @catalog.resource("me", "one").should equal(@one) end it "should canonize how resources are referred to during retrieval when just the title is provided" do @catalog.add_resource(@one) @catalog.resource("me[one]", nil).should equal(@one) end it "should not allow two resources with the same resource reference" do @catalog.add_resource(@one) # These are used to build the failure @dupe.stubs(:file) @dupe.stubs(:line) @one.stubs(:file) @one.stubs(:line) proc { @catalog.add_resource(@dupe) }.should raise_error(ArgumentError) end it "should not store objects that do not respond to :ref" do proc { @catalog.add_resource("thing") }.should raise_error(ArgumentError) end it "should remove all resources when asked" do @catalog.add_resource @one @catalog.add_resource @two @one.expects :remove @two.expects :remove @catalog.clear(true) end it "should support a mechanism for finishing resources" do @one.expects :finish @two.expects :finish @catalog.add_resource @one @catalog.add_resource @two @catalog.finalize end it "should make default resources when finalizing" do @catalog.expects(:make_default_resources) @catalog.finalize end it "should add default resources to the catalog upon creation" do @catalog.make_default_resources @catalog.resource(:schedule, "daily").should_not be_nil end it "should optionally support an initialization block and should finalize after such blocks" do @one.expects :finish @two.expects :finish config = Puppet::Node::Catalog.new("host") do |conf| conf.add_resource @one conf.add_resource @two end end it "should inform the resource that it is the resource's catalog" do @one.expects(:catalog=).with(@catalog) @catalog.add_resource @one end it "should be able to find resources by reference" do @catalog.add_resource @one @catalog.resource(@one.ref).should equal(@one) end it "should be able to find resources by reference or by type/title tuple" do @catalog.add_resource @one @catalog.resource("me", "one").should equal(@one) end it "should have a mechanism for removing resources" do @catalog.add_resource @one @one.expects :remove @catalog.remove_resource(@one) @catalog.resource(@one.ref).should be_nil @catalog.vertex?(@one).should be_false end it "should have a method for creating aliases for resources" do @catalog.add_resource @one @catalog.alias(@one, "other") @catalog.resource("me", "other").should equal(@one) end # This test is the same as the previous, but the behaviour should be explicit. it "should alias using the class name from the resource reference, not the resource class name" do @catalog.add_resource @one @catalog.alias(@one, "other") @catalog.resource("me", "other").should equal(@one) 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) end it "should not fail when a resource has duplicate aliases created" do @catalog.add_resource @one proc { @catalog.alias @one, "one" }.should_not raise_error end it "should remove resource aliases when the target resource is removed" do @catalog.add_resource @one @catalog.alias(@one, "other") @one.expects :remove @catalog.remove_resource(@one) @catalog.resource("me", "other").should be_nil end it "should add an alias for the namevar when the title and name differ" do @one.stubs(:name).returns "other" resource = Puppet::Type.type(:file).create :path => "/something", :title => "other", :content => "blah" @catalog.add_resource(resource) @catalog.resource(:file, "other").should equal(resource) @catalog.resource(:file, "/something").should equal(resource) end after do Puppet::Type.allclear end end -module ApplyingCatalogs - def setup +describe Puppet::Node::Catalog do + before :each do @catalog = Puppet::Node::Catalog.new("host") @catalog.retrieval_duration = Time.now @transaction = mock 'transaction' Puppet::Transaction.stubs(:new).returns(@transaction) @transaction.stubs(:evaluate) @transaction.stubs(:cleanup) @transaction.stubs(:addtimes) end -end -describe Puppet::Node::Catalog, " when applying" do - include ApplyingCatalogs + describe Puppet::Node::Catalog, " when applying" do - it "should create and evaluate a transaction" do - @transaction.expects(:evaluate) - @catalog.apply - end + it "should create and evaluate a transaction" do + @transaction.expects(:evaluate) + @catalog.apply + end - it "should provide the catalog time to the transaction" do - @transaction.expects(:addtimes).with do |arg| - arg[:config_retrieval].should be_instance_of(Time) - true + it "should provide the catalog time to the transaction" do + @transaction.expects(:addtimes).with do |arg| + arg[:config_retrieval].should be_instance_of(Time) + true + end + @catalog.apply end - @catalog.apply - end - it "should clean up the transaction" do - @transaction.expects :cleanup - @catalog.apply - end + it "should clean up the transaction" do + @transaction.expects :cleanup + @catalog.apply + end - it "should return the transaction" do - @catalog.apply.should equal(@transaction) - end + it "should return the transaction" do + @catalog.apply.should equal(@transaction) + end - it "should yield the transaction if a block is provided" do - @catalog.apply do |trans| - trans.should equal(@transaction) + it "should yield the transaction if a block is provided" do + @catalog.apply do |trans| + trans.should equal(@transaction) + end end - end - it "should default to not being a host catalog" do - @catalog.host_config.should be_nil - end + it "should default to not being a host catalog" do + @catalog.host_config.should be_nil + end - it "should pass supplied tags on to the transaction" do - @transaction.expects(:tags=).with(%w{one two}) - @catalog.apply(:tags => %w{one two}) - end + it "should pass supplied tags on to the transaction" do + @transaction.expects(:tags=).with(%w{one two}) + @catalog.apply(:tags => %w{one two}) + end - it "should set ignoreschedules on the transaction if specified in apply()" do - @transaction.expects(:ignoreschedules=).with(true) - @catalog.apply(:ignoreschedules => true) + it "should set ignoreschedules on the transaction if specified in apply()" do + @transaction.expects(:ignoreschedules=).with(true) + @catalog.apply(:ignoreschedules => true) + end end -end -describe Puppet::Node::Catalog, " when applying host catalogs" do - include ApplyingCatalogs + describe Puppet::Node::Catalog, " when applying host catalogs" do - # super() doesn't work in the setup method for some reason - before do - @catalog.host_config = true - end + # super() doesn't work in the setup method for some reason + before do + @catalog.host_config = true + end - it "should send a report if reporting is enabled" do - Puppet[:report] = true - @transaction.expects :send_report - @transaction.stubs :any_failed? => false - @catalog.apply - end + it "should send a report if reporting is enabled" do + Puppet[:report] = true + @transaction.expects :send_report + @transaction.stubs :any_failed? => false + @catalog.apply + end - it "should send a report if report summaries are enabled" do - Puppet[:summarize] = true - @transaction.expects :send_report - @transaction.stubs :any_failed? => false - @catalog.apply - end + it "should send a report if report summaries are enabled" do + Puppet[:summarize] = true + @transaction.expects :send_report + @transaction.stubs :any_failed? => false + @catalog.apply + end - it "should initialize the state database before applying a catalog" do - Puppet::Util::Storage.expects(:load) + it "should initialize the state database before applying a catalog" do + Puppet::Util::Storage.expects(:load) - # Short-circuit the apply, so we know we're loading before the transaction - Puppet::Transaction.expects(:new).raises ArgumentError - proc { @catalog.apply }.should raise_error(ArgumentError) - end + # Short-circuit the apply, so we know we're loading before the transaction + Puppet::Transaction.expects(:new).raises ArgumentError + proc { @catalog.apply }.should raise_error(ArgumentError) + end - it "should sync the state database after applying" do - Puppet::Util::Storage.expects(:store) - @transaction.stubs :any_failed? => false - @catalog.apply - end + it "should sync the state database after applying" do + Puppet::Util::Storage.expects(:store) + @transaction.stubs :any_failed? => false + @catalog.apply + end - after { Puppet.settings.clear } -end + after { Puppet.settings.clear } + end -describe Puppet::Node::Catalog, " when applying non-host catalogs" do - include ApplyingCatalogs + describe Puppet::Node::Catalog, " when applying non-host catalogs" do - before do - @catalog.host_config = false - end + before do + @catalog.host_config = false + end - it "should never send reports" do - Puppet[:report] = true - Puppet[:summarize] = true - @transaction.expects(:send_report).never - @catalog.apply - end + it "should never send reports" do + Puppet[:report] = true + Puppet[:summarize] = true + @transaction.expects(:send_report).never + @catalog.apply + end - it "should never modify the state database" do - Puppet::Util::Storage.expects(:load).never - Puppet::Util::Storage.expects(:store).never - @catalog.apply - end + it "should never modify the state database" do + Puppet::Util::Storage.expects(:load).never + Puppet::Util::Storage.expects(:store).never + @catalog.apply + end - after { Puppet.settings.clear } + after { Puppet.settings.clear } + end end describe Puppet::Node::Catalog, " when creating a relationship graph" do before do @catalog = Puppet::Node::Catalog.new("host") @compone = Puppet::Type::Component.create :name => "one" @comptwo = Puppet::Type::Component.create :name => "two", :require => ["class", "one"] @file = Puppet::Type.type(:file) @one = @file.create :path => "/one" @two = @file.create :path => "/two" @catalog.add_edge @compone, @one @catalog.add_edge @comptwo, @two @three = @file.create :path => "/three" @four = @file.create :path => "/four", :require => ["file", "/three"] @five = @file.create :path => "/five" @catalog.add_resource @compone, @comptwo, @one, @two, @three, @four, @five @relationships = @catalog.relationship_graph end it "should fail when trying to create a relationship graph for a relationship graph" do proc { @relationships.relationship_graph }.should raise_error(Puppet::DevError) end it "should be able to create a relationship graph" do @relationships.should be_instance_of(Puppet::Node::Catalog) end it "should copy its host_config setting to the relationship graph" do config = Puppet::Node::Catalog.new config.host_config = true config.relationship_graph.host_config.should be_true end it "should not have any components" do @relationships.vertices.find { |r| r.instance_of?(Puppet::Type::Component) }.should be_nil end it "should have all non-component resources from the catalog" do # The failures print out too much info, so i just do a class comparison @relationships.vertex?(@five).should be_true end it "should have all resource relationships set as edges" do @relationships.edge?(@three, @four).should be_true end it "should copy component relationships to all contained resources" do @relationships.edge?(@one, @two).should be_true end it "should get removed when the catalog is cleaned up" do @relationships.expects(:clear).with(false) @catalog.clear @catalog.instance_variable_get("@relationship_graph").should be_nil end it "should create a new relationship graph after clearing the old one" do @relationships.expects(:clear).with(false) @catalog.clear @catalog.relationship_graph.should be_instance_of(Puppet::Node::Catalog) end it "should look up resources in the relationship graph if not found in the main catalog" do five = stub 'five', :ref => "File[five]", :catalog= => nil @relationships.add_resource five @catalog.resource(five.ref).should equal(five) end it "should provide a method to create additional resources that also registers the resource" do args = {:name => "/yay", :ensure => :file} resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog Puppet::Type.type(:file).expects(:create).with(args).returns(resource) @catalog.create_resource :file, args @catalog.resource("File[/yay]").should equal(resource) end it "should provide a mechanism for creating implicit resources" do args = {:name => "/yay", :ensure => :file} resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog Puppet::Type.type(:file).expects(:create).with(args).returns(resource) resource.expects(:implicit=).with(true) @catalog.create_implicit_resource :file, args @catalog.resource("File[/yay]").should equal(resource) end it "should add implicit resources to the relationship graph if there is one" do args = {:name => "/yay", :ensure => :file} resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog resource.expects(:implicit=).with(true) Puppet::Type.type(:file).expects(:create).with(args).returns(resource) # build the graph relgraph = @catalog.relationship_graph @catalog.create_implicit_resource :file, args relgraph.resource("File[/yay]").should equal(resource) end it "should remove resources created mid-transaction" do args = {:name => "/yay", :ensure => :file} resource = stub 'file', :ref => "File[/yay]", :catalog= => @catalog @transaction = mock 'transaction' Puppet::Transaction.stubs(:new).returns(@transaction) @transaction.stubs(:evaluate) @transaction.stubs(:cleanup) @transaction.stubs(:addtimes) Puppet::Type.type(:file).expects(:create).with(args).returns(resource) resource.expects :remove @catalog.apply do |trans| @catalog.create_resource :file, args @catalog.resource("File[/yay]").should equal(resource) end @catalog.resource("File[/yay]").should be_nil end it "should remove resources from the relationship graph if it exists" do @catalog.remove_resource(@one) @catalog.relationship_graph.vertex?(@one).should be_false end after do Puppet::Type.allclear end end describe Puppet::Node::Catalog, " when writing dot files" do before do @catalog = Puppet::Node::Catalog.new("host") @name = :test @file = File.join(Puppet[:graphdir], @name.to_s + ".dot") end it "should only write when it is a host catalog" do File.expects(:open).with(@file).never @catalog.host_config = false Puppet[:graph] = true @catalog.write_graph(@name) end it "should only write when graphing is enabled" do File.expects(:open).with(@file).never @catalog.host_config = true Puppet[:graph] = false @catalog.write_graph(@name) end it "should write a dot file based on the passed name" do File.expects(:open).with(@file, "w").yields(stub("file", :puts => nil)) @catalog.expects(:to_dot).with("name" => @name.to_s.capitalize) @catalog.host_config = true Puppet[:graph] = true @catalog.write_graph(@name) end after do Puppet.settings.clear end end describe Puppet::Node::Catalog, " when indirecting" do before do @indirection = mock 'indirection' Puppet::Indirector::Indirection.clear_cache end it "should redirect to the indirection for retrieval" do Puppet::Node::Catalog.stubs(:indirection).returns(@indirection) @indirection.expects(:find).with(:myconfig) Puppet::Node::Catalog.find(:myconfig) end it "should default to the 'compiler' terminus" do Puppet::Node::Catalog.indirection.terminus_class.should == :compiler end after do mocha_verify Puppet::Indirector::Indirection.clear_cache end end describe Puppet::Node::Catalog, " when converting to yaml" do before do @catalog = Puppet::Node::Catalog.new("me") @catalog.add_edge("one", "two") end it "should be able to be dumped to yaml" do YAML.dump(@catalog).should be_instance_of(String) end end describe Puppet::Node::Catalog, " when converting from yaml" do before do @catalog = Puppet::Node::Catalog.new("me") @catalog.add_edge("one", "two") text = YAML.dump(@catalog) @newcatalog = YAML.load(text) end it "should get converted back to a catalog" do @newcatalog.should be_instance_of(Puppet::Node::Catalog) end it "should have all vertices" do @newcatalog.vertex?("one").should be_true @newcatalog.vertex?("two").should be_true end it "should have all edges" do @newcatalog.edge?("one", "two").should be_true end end diff --git a/spec/unit/parser/ast/hostclass.rb b/spec/unit/parser/ast/hostclass.rb index 422861857..a53c3b092 100755 --- a/spec/unit/parser/ast/hostclass.rb +++ b/spec/unit/parser/ast/hostclass.rb @@ -1,131 +1,129 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' -module HostClassTesting - def setup +describe Puppet::Parser::AST::HostClass do + before :each do @node = Puppet::Node.new "testnode" @parser = Puppet::Parser::Parser.new :environment => "development" @scope_resource = stub 'scope_resource', :builtin? => true @compiler = Puppet::Parser::Compiler.new(@node, @parser) @scope = @compiler.topscope end -end -describe Puppet::Parser::AST::HostClass, "when evaluating" do - include HostClassTesting + describe Puppet::Parser::AST::HostClass, "when evaluating" do - before do - @top = @parser.newclass "top" - @middle = @parser.newclass "middle", :parent => "top" - end + before do + @top = @parser.newclass "top" + @middle = @parser.newclass "middle", :parent => "top" + end - it "should create a resource that references itself" do - @top.evaluate(@scope) + it "should create a resource that references itself" do + @top.evaluate(@scope) - @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) - end + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end - it "should evaluate the parent class if one exists" do - @middle.evaluate(@scope) + it "should evaluate the parent class if one exists" do + @middle.evaluate(@scope) - @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) - end + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end - it "should fail to evaluate if a parent class is defined but cannot be found" do - othertop = @parser.newclass "something", :parent => "yay" - lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) - end + it "should fail to evaluate if a parent class is defined but cannot be found" do + othertop = @parser.newclass "something", :parent => "yay" + lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) + end - it "should not create a new resource if one already exists" do - @compiler.catalog.expects(:resource).with(:class, "top").returns("something") - @compiler.catalog.expects(:add_resource).never - @top.evaluate(@scope) - end + it "should not create a new resource if one already exists" do + @compiler.catalog.expects(:resource).with(:class, "top").returns("something") + @compiler.catalog.expects(:add_resource).never + @top.evaluate(@scope) + end - it "should not create a new parent resource if one already exists and it has a parent class" do - @top.evaluate(@scope) + it "should not create a new parent resource if one already exists and it has a parent class" do + @top.evaluate(@scope) - top_resource = @compiler.catalog.resource(:class, "top") + top_resource = @compiler.catalog.resource(:class, "top") - @middle.evaluate(@scope) + @middle.evaluate(@scope) - @compiler.catalog.resource(:class, "top").should equal(top_resource) - end + @compiler.catalog.resource(:class, "top").should equal(top_resource) + end - # #795 - tag before evaluation. - it "should tag the catalog with the resource tags when it is evaluated" do - @middle.evaluate(@scope) + # #795 - tag before evaluation. + it "should tag the catalog with the resource tags when it is evaluated" do + @middle.evaluate(@scope) - @compiler.catalog.should be_tagged("middle") - end + @compiler.catalog.should be_tagged("middle") + end - it "should tag the catalog with the parent class tags when it is evaluated" do - @middle.evaluate(@scope) + it "should tag the catalog with the parent class tags when it is evaluated" do + @middle.evaluate(@scope) - @compiler.catalog.should be_tagged("top") + @compiler.catalog.should be_tagged("top") + end end -end -describe Puppet::Parser::AST::HostClass, "when evaluating code" do - include HostClassTesting + describe Puppet::Parser::AST::HostClass, "when evaluating code" do - before do - @top_resource = stub "top_resource" - @top = @parser.newclass "top", :code => @top_resource + before do + @top_resource = stub "top_resource" + @top = @parser.newclass "top", :code => @top_resource - @middle_resource = stub "middle_resource" - @middle = @parser.newclass "top::middle", :parent => "top", :code => @middle_resource - end + @middle_resource = stub "middle_resource" + @middle = @parser.newclass "top::middle", :parent => "top", :code => @middle_resource + end - it "should set its namespace to its fully qualified name" do - @middle.namespace.should == "top::middle" - end + it "should set its namespace to its fully qualified name" do + @middle.namespace.should == "top::middle" + end - it "should evaluate the code referred to by the class" do - @top_resource.expects(:safeevaluate) + it "should evaluate the code referred to by the class" do + @top_resource.expects(:safeevaluate) - resource = @top.evaluate(@scope) + resource = @top.evaluate(@scope) - @top.evaluate_code(resource) - end + @top.evaluate_code(resource) + end - it "should evaluate the parent class's code if it has a parent" do - @top_resource.expects(:safeevaluate) - @middle_resource.expects(:safeevaluate) + it "should evaluate the parent class's code if it has a parent" do + @top_resource.expects(:safeevaluate) + @middle_resource.expects(:safeevaluate) - resource = @middle.evaluate(@scope) + resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) - end + @middle.evaluate_code(resource) + end - it "should not evaluate the parent class's code if the parent has already been evaluated" do - @top_resource.stubs(:safeevaluate) - resource = @top.evaluate(@scope) - @top.evaluate_code(resource) + it "should not evaluate the parent class's code if the parent has already been evaluated" do + @top_resource.stubs(:safeevaluate) + resource = @top.evaluate(@scope) + @top.evaluate_code(resource) - @top_resource.expects(:safeevaluate).never - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) - end + @top_resource.expects(:safeevaluate).never + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + end - it "should use the parent class's scope as its parent scope" do - @top_resource.stubs(:safeevaluate) - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) + it "should use the parent class's scope as its parent scope" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) - @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) - end + @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) + end - it "should add the parent class's namespace to its namespace search path" do - @top_resource.stubs(:safeevaluate) - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) + it "should add the parent class's namespace to its namespace search path" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) - @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + end end -end +end \ No newline at end of file diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb index 340630194..757934415 100755 --- a/spec/unit/parser/ast/node.rb +++ b/spec/unit/parser/ast/node.rb @@ -1,127 +1,125 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' -module ASTNodeTesting - def setup +describe Puppet::Parser::AST::Node do + before :each do @node = Puppet::Node.new "testnode" @parser = Puppet::Parser::Parser.new :environment => "development" @scope_resource = stub 'scope_resource', :builtin? => true @compiler = Puppet::Parser::Compiler.new(@node, @parser) @scope = @compiler.topscope end -end -describe Puppet::Parser::AST::Node, "when evaluating" do - include ASTNodeTesting + describe Puppet::Parser::AST::Node, "when evaluating" do - before do - @top = @parser.newnode("top").shift - @middle = @parser.newnode("middle", :parent => "top").shift - end + before do + @top = @parser.newnode("top").shift + @middle = @parser.newnode("middle", :parent => "top").shift + end - it "should create a resource that references itself" do - @top.evaluate(@scope) + it "should create a resource that references itself" do + @top.evaluate(@scope) - @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) - end + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end - it "should evaluate the parent class if one exists" do - @middle.evaluate(@scope) + it "should evaluate the parent class if one exists" do + @middle.evaluate(@scope) - @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) - end + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end - it "should fail to evaluate if a parent class is defined but cannot be found" do - othertop = @parser.newnode("something", :parent => "yay").shift - lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) - end + it "should fail to evaluate if a parent class is defined but cannot be found" do + othertop = @parser.newnode("something", :parent => "yay").shift + lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) + end - it "should not create a new resource if one already exists" do - @compiler.catalog.expects(:resource).with(:node, "top").returns("something") - @compiler.catalog.expects(:add_resource).never - @top.evaluate(@scope) - end + it "should not create a new resource if one already exists" do + @compiler.catalog.expects(:resource).with(:node, "top").returns("something") + @compiler.catalog.expects(:add_resource).never + @top.evaluate(@scope) + end - it "should not create a new parent resource if one already exists and it has a parent class" do - @top.evaluate(@scope) + it "should not create a new parent resource if one already exists and it has a parent class" do + @top.evaluate(@scope) - top_resource = @compiler.catalog.resource(:node, "top") + top_resource = @compiler.catalog.resource(:node, "top") - @middle.evaluate(@scope) + @middle.evaluate(@scope) - @compiler.catalog.resource(:node, "top").should equal(top_resource) - end + @compiler.catalog.resource(:node, "top").should equal(top_resource) + end - # #795 - tag before evaluation. - it "should tag the catalog with the resource tags when it is evaluated" do - @middle.evaluate(@scope) + # #795 - tag before evaluation. + it "should tag the catalog with the resource tags when it is evaluated" do + @middle.evaluate(@scope) - @compiler.catalog.should be_tagged("middle") - end + @compiler.catalog.should be_tagged("middle") + end - it "should tag the catalog with the parent class tags when it is evaluated" do - @middle.evaluate(@scope) + it "should tag the catalog with the parent class tags when it is evaluated" do + @middle.evaluate(@scope) - @compiler.catalog.should be_tagged("top") + @compiler.catalog.should be_tagged("top") + end end -end -describe Puppet::Parser::AST::Node, "when evaluating code" do - include ASTNodeTesting + describe Puppet::Parser::AST::Node, "when evaluating code" do - before do - @top_resource = stub "top_resource" - @top = @parser.newnode("top", :code => @top_resource).shift + before do + @top_resource = stub "top_resource" + @top = @parser.newnode("top", :code => @top_resource).shift - @middle_resource = stub "middle_resource" - @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift - end + @middle_resource = stub "middle_resource" + @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift + end - it "should evaluate the code referred to by the class" do - @top_resource.expects(:safeevaluate) + it "should evaluate the code referred to by the class" do + @top_resource.expects(:safeevaluate) - resource = @top.evaluate(@scope) + resource = @top.evaluate(@scope) - @top.evaluate_code(resource) - end + @top.evaluate_code(resource) + end - it "should evaluate the parent class's code if it has a parent" do - @top_resource.expects(:safeevaluate) - @middle_resource.expects(:safeevaluate) + it "should evaluate the parent class's code if it has a parent" do + @top_resource.expects(:safeevaluate) + @middle_resource.expects(:safeevaluate) - resource = @middle.evaluate(@scope) + resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) - end + @middle.evaluate_code(resource) + end - it "should not evaluate the parent class's code if the parent has already been evaluated" do - @top_resource.stubs(:safeevaluate) - resource = @top.evaluate(@scope) - @top.evaluate_code(resource) + it "should not evaluate the parent class's code if the parent has already been evaluated" do + @top_resource.stubs(:safeevaluate) + resource = @top.evaluate(@scope) + @top.evaluate_code(resource) - @top_resource.expects(:safeevaluate).never - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) - end + @top_resource.expects(:safeevaluate).never + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + end - it "should use the parent class's scope as its parent scope" do - @top_resource.stubs(:safeevaluate) - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) + it "should use the parent class's scope as its parent scope" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) - @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) - end + @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) + end - it "should add the parent class's namespace to its namespace search path" do - @top_resource.stubs(:safeevaluate) - @middle_resource.stubs(:safeevaluate) - resource = @middle.evaluate(@scope) - @middle.evaluate_code(resource) + it "should add the parent class's namespace to its namespace search path" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) - @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + end end -end +end \ No newline at end of file diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb index 6b821977d..9980f2c6a 100755 --- a/spec/unit/parser/compiler.rb +++ b/spec/unit/parser/compiler.rb @@ -1,544 +1,532 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' -module CompilerTesting - def setup +describe Puppet::Parser::Compiler do + before :each do @node = Puppet::Node.new "testnode" @parser = Puppet::Parser::Parser.new :environment => "development" @scope_resource = stub 'scope_resource', :builtin? => true @scope = stub 'scope', :resource => @scope_resource, :source => mock("source") @compiler = Puppet::Parser::Compiler.new(@node, @parser) end -end - -describe Puppet::Parser::Compiler do - include CompilerTesting - - it "should be able to store references to class scopes" do - lambda { @compiler.class_set "myname", "myscope" }.should_not raise_error - end - - it "should be able to retrieve class scopes by name" do - @compiler.class_set "myname", "myscope" - @compiler.class_scope("myname").should == "myscope" - end - - it "should be able to retrieve class scopes by object" do - klass = mock 'ast_class' - klass.expects(:classname).returns("myname") - @compiler.class_set "myname", "myscope" - @compiler.class_scope(klass).should == "myscope" - end - - it "should be able to return a class list containing all set classes" do - @compiler.class_set "", "empty" - @compiler.class_set "one", "yep" - @compiler.class_set "two", "nope" - - @compiler.classlist.sort.should == %w{one two}.sort - end -end -describe Puppet::Parser::Compiler, " when initializing" do - include CompilerTesting - - it "should set its node attribute" do - @compiler.node.should equal(@node) - end - - it "should set its parser attribute" do - @compiler.parser.should equal(@parser) - end + describe Puppet::Parser::Compiler do - it "should detect when ast nodes are absent" do - @compiler.ast_nodes?.should be_false - end + it "should be able to store references to class scopes" do + lambda { @compiler.class_set "myname", "myscope" }.should_not raise_error + end - it "should detect when ast nodes are present" do - @parser.nodes["testing"] = "yay" - @compiler.ast_nodes?.should be_true - end -end + it "should be able to retrieve class scopes by name" do + @compiler.class_set "myname", "myscope" + @compiler.class_scope("myname").should == "myscope" + end -describe Puppet::Parser::Compiler, "when managing scopes" do - include CompilerTesting + it "should be able to retrieve class scopes by object" do + klass = mock 'ast_class' + klass.expects(:classname).returns("myname") + @compiler.class_set "myname", "myscope" + @compiler.class_scope(klass).should == "myscope" + end - it "should create a top scope" do - @compiler.topscope.should be_instance_of(Puppet::Parser::Scope) - end + it "should be able to return a class list containing all set classes" do + @compiler.class_set "", "empty" + @compiler.class_set "one", "yep" + @compiler.class_set "two", "nope" - it "should be able to create new scopes" do - @compiler.newscope(@compiler.topscope).should be_instance_of(Puppet::Parser::Scope) + @compiler.classlist.sort.should == %w{one two}.sort + end end - it "should correctly set the level of newly created scopes" do - @compiler.newscope(@compiler.topscope, :level => 5).level.should == 5 - end + describe Puppet::Parser::Compiler, " when initializing" do - it "should set the parent scope of the new scope to be the passed-in parent" do - scope = mock 'scope' - newscope = @compiler.newscope(scope) + it "should set its node attribute" do + @compiler.node.should equal(@node) + end - @compiler.parent(newscope).should equal(scope) - end -end + it "should set its parser attribute" do + @compiler.parser.should equal(@parser) + end -describe Puppet::Parser::Compiler, " when compiling" do - include CompilerTesting + it "should detect when ast nodes are absent" do + @compiler.ast_nodes?.should be_false + end - def compile_methods - [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, - :finish, :store, :extract] + it "should detect when ast nodes are present" do + @parser.nodes["testing"] = "yay" + @compiler.ast_nodes?.should be_true + end end - # Stub all of the main compile methods except the ones we're specifically interested in. - def compile_stub(*except) - (compile_methods - except).each { |m| @compiler.stubs(m) } - end + describe Puppet::Parser::Compiler, "when managing scopes" do - it "should set node parameters as variables in the top scope" do - params = {"a" => "b", "c" => "d"} - @node.stubs(:parameters).returns(params) - compile_stub(:set_node_parameters) - @compiler.compile - @compiler.topscope.lookupvar("a").should == "b" - @compiler.topscope.lookupvar("c").should == "d" - end + it "should create a top scope" do + @compiler.topscope.should be_instance_of(Puppet::Parser::Scope) + end - it "should evaluate any existing classes named in the node" do - classes = %w{one two three four} - main = stub 'main' - one = stub 'one', :classname => "one" - three = stub 'three', :classname => "three" - @node.stubs(:name).returns("whatever") - @node.stubs(:classes).returns(classes) + it "should be able to create new scopes" do + @compiler.newscope(@compiler.topscope).should be_instance_of(Puppet::Parser::Scope) + end - @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) - @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } - end + it "should correctly set the level of newly created scopes" do + @compiler.newscope(@compiler.topscope, :level => 5).level.should == 5 + end - it "should enable ast_nodes if the parser has any nodes" do - @parser.expects(:nodes).returns(:one => :yay) - @compiler.ast_nodes?.should be_true - end + it "should set the parent scope of the new scope to be the passed-in parent" do + scope = mock 'scope' + newscope = @compiler.newscope(scope) - it "should disable ast_nodes if the parser has no nodes" do - @parser.expects(:nodes).returns({}) - @compiler.ast_nodes?.should be_false + @compiler.parent(newscope).should equal(scope) + end end - it "should evaluate the main class if it exists" do - compile_stub(:evaluate_main) - main_class = mock 'main_class' - main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } - @compiler.topscope.expects(:source=).with(main_class) - @parser.stubs(:findclass).with("", "").returns(main_class) - - @compiler.compile - end + describe Puppet::Parser::Compiler, " when compiling" do - it "should evaluate any node classes" do - @node.stubs(:classes).returns(%w{one two three four}) - @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope) - @compiler.send(:evaluate_node_classes) - end + def compile_methods + [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, + :finish, :store, :extract] + end - it "should evaluate all added collections" do - colls = [] - # And when the collections fail to evaluate. - colls << mock("coll1-false") - colls << mock("coll2-false") - colls.each { |c| c.expects(:evaluate).returns(false) } + # Stub all of the main compile methods except the ones we're specifically interested in. + def compile_stub(*except) + (compile_methods - except).each { |m| @compiler.stubs(m) } + end - @compiler.add_collection(colls[0]) - @compiler.add_collection(colls[1]) + it "should set node parameters as variables in the top scope" do + params = {"a" => "b", "c" => "d"} + @node.stubs(:parameters).returns(params) + compile_stub(:set_node_parameters) + @compiler.compile + @compiler.topscope.lookupvar("a").should == "b" + @compiler.topscope.lookupvar("c").should == "d" + end - compile_stub(:evaluate_generators) - @compiler.compile - end + it "should evaluate any existing classes named in the node" do + classes = %w{one two three four} + main = stub 'main' + one = stub 'one', :classname => "one" + three = stub 'three', :classname => "three" + @node.stubs(:name).returns("whatever") + @node.stubs(:classes).returns(classes) - it "should ignore builtin resources" do - resource = stub 'builtin', :ref => "File[testing]", :builtin? => true + @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) + @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } + end + + it "should enable ast_nodes if the parser has any nodes" do + @parser.expects(:nodes).returns(:one => :yay) + @compiler.ast_nodes?.should be_true + end + + it "should disable ast_nodes if the parser has no nodes" do + @parser.expects(:nodes).returns({}) + @compiler.ast_nodes?.should be_false + end + + it "should evaluate the main class if it exists" do + compile_stub(:evaluate_main) + main_class = mock 'main_class' + main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } + @compiler.topscope.expects(:source=).with(main_class) + @parser.stubs(:findclass).with("", "").returns(main_class) + + @compiler.compile + end - @compiler.add_resource(@scope, resource) - resource.expects(:evaluate).never + it "should evaluate any node classes" do + @node.stubs(:classes).returns(%w{one two three four}) + @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope) + @compiler.send(:evaluate_node_classes) + end + + it "should evaluate all added collections" do + colls = [] + # And when the collections fail to evaluate. + colls << mock("coll1-false") + colls << mock("coll2-false") + colls.each { |c| c.expects(:evaluate).returns(false) } + + @compiler.add_collection(colls[0]) + @compiler.add_collection(colls[1]) + + compile_stub(:evaluate_generators) + @compiler.compile + end + + it "should ignore builtin resources" do + resource = stub 'builtin', :ref => "File[testing]", :builtin? => true + + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never - @compiler.compile - end + @compiler.compile + end - it "should evaluate unevaluated resources" do - resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false - @compiler.add_resource(@scope, resource) + it "should evaluate unevaluated resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false + @compiler.add_resource(@scope, resource) - # We have to now mark the resource as evaluated - resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns true } + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns true } - @compiler.compile - end + @compiler.compile + end - it "should not evaluate already-evaluated resources" do - resource = stub 'already_evaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => true, :virtual? => false - @compiler.add_resource(@scope, resource) - resource.expects(:evaluate).never + it "should not evaluate already-evaluated resources" do + resource = stub 'already_evaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => true, :virtual? => false + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never - @compiler.compile - end + @compiler.compile + end - it "should evaluate unevaluated resources created by evaluating other resources" do - resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false - @compiler.add_resource(@scope, resource) + it "should evaluate unevaluated resources created by evaluating other resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false + @compiler.add_resource(@scope, resource) - resource2 = stub 'created', :ref => "File[other]", :builtin? => false, :evaluated? => false, :virtual? => false + resource2 = stub 'created', :ref => "File[other]", :builtin? => false, :evaluated? => false, :virtual? => false - # We have to now mark the resource as evaluated - resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns(true); @compiler.add_resource(@scope, resource2) } - resource2.expects(:evaluate).with { |*whatever| resource2.stubs(:evaluated?).returns(true) } + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns(true); @compiler.add_resource(@scope, resource2) } + resource2.expects(:evaluate).with { |*whatever| resource2.stubs(:evaluated?).returns(true) } - @compiler.compile - end + @compiler.compile + end - it "should call finish() on all resources" do - # Add a resource that does respond to :finish - resource = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish" - resource.expects(:finish) + it "should call finish() on all resources" do + # Add a resource that does respond to :finish + resource = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish" + resource.expects(:finish) - @compiler.add_resource(@scope, resource) + @compiler.add_resource(@scope, resource) - # And one that does not - dnf = stub "dnf", :ref => "File[dnf]" + # And one that does not + dnf = stub "dnf", :ref => "File[dnf]" - @compiler.add_resource(@scope, dnf) + @compiler.add_resource(@scope, dnf) - @compiler.send(:finish) - end + @compiler.send(:finish) + end - it "should add resources that do not conflict with existing resources" do - resource = stub "noconflict", :ref => "File[yay]" - @compiler.add_resource(@scope, resource) + it "should add resources that do not conflict with existing resources" do + resource = stub "noconflict", :ref => "File[yay]" + @compiler.add_resource(@scope, resource) - @compiler.catalog.should be_vertex(resource) - end + @compiler.catalog.should be_vertex(resource) + end - it "should fail to add resources that conflict with existing resources" do - type = stub 'faketype', :isomorphic? => true, :name => "mytype" - Puppet::Type.stubs(:type).with("mytype").returns(type) + it "should fail to add resources that conflict with existing resources" do + type = stub 'faketype', :isomorphic? => true, :name => "mytype" + Puppet::Type.stubs(:type).with("mytype").returns(type) - resource1 = stub "iso1conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 - resource2 = stub "iso2conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 + resource1 = stub "iso1conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 + resource2 = stub "iso2conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 - @compiler.add_resource(@scope, resource1) - lambda { @compiler.add_resource(@scope, resource2) }.should raise_error(ArgumentError) - end + @compiler.add_resource(@scope, resource1) + lambda { @compiler.add_resource(@scope, resource2) }.should raise_error(ArgumentError) + end - it "should have a method for looking up resources" do - resource = stub 'resource', :ref => "Yay[foo]" - @compiler.add_resource(@scope, resource) - @compiler.findresource("Yay[foo]").should equal(resource) - end + it "should have a method for looking up resources" do + resource = stub 'resource', :ref => "Yay[foo]" + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay[foo]").should equal(resource) + end - it "should be able to look resources up by type and title" do - resource = stub 'resource', :ref => "Yay[foo]" - @compiler.add_resource(@scope, resource) - @compiler.findresource("Yay", "foo").should equal(resource) - end + it "should be able to look resources up by type and title" do + resource = stub 'resource', :ref => "Yay[foo]" + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay", "foo").should equal(resource) + end - it "should not evaluate virtual defined resources" do - resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => true - @compiler.add_resource(@scope, resource) + it "should not evaluate virtual defined resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => true + @compiler.add_resource(@scope, resource) - resource.expects(:evaluate).never + resource.expects(:evaluate).never - @compiler.compile + @compiler.compile + end end -end -describe Puppet::Parser::Compiler, " when evaluating collections" do - include CompilerTesting + describe Puppet::Parser::Compiler, " when evaluating collections" do - it "should evaluate each collection" do - 2.times { |i| - coll = mock 'coll%s' % i - @compiler.add_collection(coll) + it "should evaluate each collection" do + 2.times { |i| + coll = mock 'coll%s' % i + @compiler.add_collection(coll) - # This is the hard part -- we have to emulate the fact that - # collections delete themselves if they are done evaluating. - coll.expects(:evaluate).with do - @compiler.delete_collection(coll) - end - } - - @compiler.class.publicize_methods(:evaluate_collections) { @compiler.evaluate_collections } - end + # This is the hard part -- we have to emulate the fact that + # collections delete themselves if they are done evaluating. + coll.expects(:evaluate).with do + @compiler.delete_collection(coll) + end + } - it "should not fail when there are unevaluated resource collections that do not refer to specific resources" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns(nil) + @compiler.class.publicize_methods(:evaluate_collections) { @compiler.evaluate_collections } + end - @compiler.add_collection(coll) + it "should not fail when there are unevaluated resource collections that do not refer to specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(nil) - lambda { @compiler.compile }.should_not raise_error - end + @compiler.add_collection(coll) - it "should fail when there are unevaluated resource collections that refer to a specific resource" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns(:something) + lambda { @compiler.compile }.should_not raise_error + end - @compiler.add_collection(coll) + it "should fail when there are unevaluated resource collections that refer to a specific resource" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(:something) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) - end + @compiler.add_collection(coll) - it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns([:one, :two]) + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end - @compiler.add_collection(coll) + it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns([:one, :two]) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + @compiler.add_collection(coll) + + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end end -end -describe Puppet::Parser::Compiler, "when told to evaluate missing classes" do - include CompilerTesting + describe Puppet::Parser::Compiler, "when told to evaluate missing classes" do - it "should fail if there's no source listed for the scope" do - scope = stub 'scope', :source => nil - proc { @compiler.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) - end + it "should fail if there's no source listed for the scope" do + scope = stub 'scope', :source => nil + proc { @compiler.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) + end - it "should tag the catalog with the name of each not-found class" do - @compiler.catalog.expects(:tag).with("notfound") - @scope.expects(:findclass).with("notfound").returns(nil) - @compiler.evaluate_classes(%w{notfound}, @scope) + it "should tag the catalog with the name of each not-found class" do + @compiler.catalog.expects(:tag).with("notfound") + @scope.expects(:findclass).with("notfound").returns(nil) + @compiler.evaluate_classes(%w{notfound}, @scope) + end end -end -describe Puppet::Parser::Compiler, " when evaluating found classes" do - include CompilerTesting + describe Puppet::Parser::Compiler, " when evaluating found classes" do - before do - @class = stub 'class', :classname => "my::class" - @scope.stubs(:findclass).with("myclass").returns(@class) + before do + @class = stub 'class', :classname => "my::class" + @scope.stubs(:findclass).with("myclass").returns(@class) - @resource = stub 'resource', :ref => "Class[myclass]" - end + @resource = stub 'resource', :ref => "Class[myclass]" + end - it "should evaluate each class" do - @compiler.catalog.stubs(:tag) + it "should evaluate each class" do + @compiler.catalog.stubs(:tag) - @class.expects(:evaluate).with(@scope) + @class.expects(:evaluate).with(@scope) - @compiler.evaluate_classes(%w{myclass}, @scope) - end + @compiler.evaluate_classes(%w{myclass}, @scope) + end - it "should not evaluate the resources created for found classes unless asked" do - @compiler.catalog.stubs(:tag) + it "should not evaluate the resources created for found classes unless asked" do + @compiler.catalog.stubs(:tag) - @resource.expects(:evaluate).never + @resource.expects(:evaluate).never - @class.expects(:evaluate).returns(@resource) + @class.expects(:evaluate).returns(@resource) - @compiler.evaluate_classes(%w{myclass}, @scope) - end + @compiler.evaluate_classes(%w{myclass}, @scope) + end - it "should immediately evaluate the resources created for found classes when asked" do - @compiler.catalog.stubs(:tag) + it "should immediately evaluate the resources created for found classes when asked" do + @compiler.catalog.stubs(:tag) - @resource.expects(:evaluate) - @class.expects(:evaluate).returns(@resource) + @resource.expects(:evaluate) + @class.expects(:evaluate).returns(@resource) - @compiler.evaluate_classes(%w{myclass}, @scope, false) - end + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end - it "should skip classes that have already been evaluated" do - @compiler.catalog.stubs(:tag) + it "should skip classes that have already been evaluated" do + @compiler.catalog.stubs(:tag) - @compiler.expects(:class_scope).with(@class).returns("something") + @compiler.expects(:class_scope).with(@class).returns("something") - @compiler.expects(:add_resource).never + @compiler.expects(:add_resource).never - @resource.expects(:evaluate).never + @resource.expects(:evaluate).never - Puppet::Parser::Resource.expects(:new).never - @compiler.evaluate_classes(%w{myclass}, @scope, false) - end + Puppet::Parser::Resource.expects(:new).never + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end - it "should return the list of found classes" do - @compiler.catalog.stubs(:tag) + it "should return the list of found classes" do + @compiler.catalog.stubs(:tag) - @compiler.stubs(:add_resource) - @scope.stubs(:findclass).with("notfound").returns(nil) + @compiler.stubs(:add_resource) + @scope.stubs(:findclass).with("notfound").returns(nil) - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @class.stubs :evaluate - @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} + Puppet::Parser::Resource.stubs(:new).returns(@resource) + @class.stubs :evaluate + @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} + end end -end -describe Puppet::Parser::Compiler, " when evaluating AST nodes with no AST nodes present" do - include CompilerTesting + describe Puppet::Parser::Compiler, " when evaluating AST nodes with no AST nodes present" do - it "should do nothing" do - @compiler.expects(:ast_nodes?).returns(false) - @compiler.parser.expects(:nodes).never - Puppet::Parser::Resource.expects(:new).never + it "should do nothing" do + @compiler.expects(:ast_nodes?).returns(false) + @compiler.parser.expects(:nodes).never + Puppet::Parser::Resource.expects(:new).never - @compiler.send(:evaluate_ast_node) + @compiler.send(:evaluate_ast_node) + end end -end -describe Puppet::Parser::Compiler, " when evaluating AST nodes with AST nodes present" do - include CompilerTesting + describe Puppet::Parser::Compiler, " when evaluating AST nodes with AST nodes present" do - before do - @nodes = mock 'node_hash' - @compiler.stubs(:ast_nodes?).returns(true) - @compiler.parser.stubs(:nodes).returns(@nodes) + before do + @nodes = mock 'node_hash' + @compiler.stubs(:ast_nodes?).returns(true) + @compiler.parser.stubs(:nodes).returns(@nodes) - # Set some names for our test - @node.stubs(:names).returns(%w{a b c}) - @nodes.stubs(:[]).with("a").returns(nil) - @nodes.stubs(:[]).with("b").returns(nil) - @nodes.stubs(:[]).with("c").returns(nil) + # Set some names for our test + @node.stubs(:names).returns(%w{a b c}) + @nodes.stubs(:[]).with("a").returns(nil) + @nodes.stubs(:[]).with("b").returns(nil) + @nodes.stubs(:[]).with("c").returns(nil) - # It should check this last, of course. - @nodes.stubs(:[]).with("default").returns(nil) - end + # It should check this last, of course. + @nodes.stubs(:[]).with("default").returns(nil) + end - it "should fail if the named node cannot be found" do - proc { @compiler.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) - end + it "should fail if the named node cannot be found" do + proc { @compiler.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) + end - it "should evaluate the first node class matching the node name" do - node_class = stub 'node', :classname => "c", :evaluate_code => nil - @nodes.stubs(:[]).with("c").returns(node_class) + it "should evaluate the first node class matching the node name" do + node_class = stub 'node', :classname => "c", :evaluate_code => nil + @nodes.stubs(:[]).with("c").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil - node_class.expects(:evaluate).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil + node_class.expects(:evaluate).returns(node_resource) - @compiler.compile - end + @compiler.compile + end - it "should match the default node if no matching node can be found" do - node_class = stub 'node', :classname => "default", :evaluate_code => nil - @nodes.stubs(:[]).with("default").returns(node_class) + it "should match the default node if no matching node can be found" do + node_class = stub 'node', :classname => "default", :evaluate_code => nil + @nodes.stubs(:[]).with("default").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil - node_class.expects(:evaluate).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil + node_class.expects(:evaluate).returns(node_resource) - @compiler.compile - end + @compiler.compile + end - it "should evaluate the node resource immediately rather than using lazy evaluation" do - node_class = stub 'node', :classname => "c" - @nodes.stubs(:[]).with("c").returns(node_class) + it "should evaluate the node resource immediately rather than using lazy evaluation" do + node_class = stub 'node', :classname => "c" + @nodes.stubs(:[]).with("c").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[c]" - node_class.expects(:evaluate).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[c]" + node_class.expects(:evaluate).returns(node_resource) - node_resource.expects(:evaluate) + node_resource.expects(:evaluate) - @compiler.send(:evaluate_ast_node) - end + @compiler.send(:evaluate_ast_node) + end - it "should set the node's scope as the top scope" do - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil - node_class = stub 'node', :classname => "c", :evaluate => node_resource + it "should set the node's scope as the top scope" do + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil + node_class = stub 'node', :classname => "c", :evaluate => node_resource - @nodes.stubs(:[]).with("c").returns(node_class) + @nodes.stubs(:[]).with("c").returns(node_class) - # The #evaluate method normally does this. - scope = stub 'scope', :source => "mysource" - @compiler.class_set(node_class.classname, scope) - node_resource.stubs(:evaluate) + # The #evaluate method normally does this. + scope = stub 'scope', :source => "mysource" + @compiler.class_set(node_class.classname, scope) + node_resource.stubs(:evaluate) - @compiler.compile + @compiler.compile - @compiler.topscope.should equal(scope) + @compiler.topscope.should equal(scope) + end end -end -describe Puppet::Parser::Compiler, "when storing compiled resources" do - include CompilerTesting + describe Puppet::Parser::Compiler, "when storing compiled resources" do - it "should store the resources" do - Puppet.features.expects(:rails?).returns(true) - Puppet::Rails.expects(:connect) + it "should store the resources" do + Puppet.features.expects(:rails?).returns(true) + Puppet::Rails.expects(:connect) - @compiler.catalog.expects(:vertices).returns(:resources) + @compiler.catalog.expects(:vertices).returns(:resources) - @compiler.expects(:store_to_active_record).with(@node, :resources) - @compiler.send(:store) - end + @compiler.expects(:store_to_active_record).with(@node, :resources) + @compiler.send(:store) + end - it "should store to active_record" do - @node.expects(:name).returns("myname") - Puppet::Rails::Host.stubs(:transaction).yields - Puppet::Rails::Host.expects(:store).with(@node, :resources) - @compiler.send(:store_to_active_record, @node, :resources) + it "should store to active_record" do + @node.expects(:name).returns("myname") + Puppet::Rails::Host.stubs(:transaction).yields + Puppet::Rails::Host.expects(:store).with(@node, :resources) + @compiler.send(:store_to_active_record, @node, :resources) + end end -end -describe Puppet::Parser::Compiler, "when managing resource overrides" do - include CompilerTesting + describe Puppet::Parser::Compiler, "when managing resource overrides" do - before do - @override = stub 'override', :ref => "My[ref]" - @resource = stub 'resource', :ref => "My[ref]", :builtin? => true - end + before do + @override = stub 'override', :ref => "My[ref]" + @resource = stub 'resource', :ref => "My[ref]", :builtin? => true + end - it "should be able to store overrides" do - lambda { @compiler.add_override(@override) }.should_not raise_error - end + it "should be able to store overrides" do + lambda { @compiler.add_override(@override) }.should_not raise_error + end - it "should apply overrides to the appropriate resources" do - @compiler.add_resource(@scope, @resource) - @resource.expects(:merge).with(@override) + it "should apply overrides to the appropriate resources" do + @compiler.add_resource(@scope, @resource) + @resource.expects(:merge).with(@override) - @compiler.add_override(@override) + @compiler.add_override(@override) - @compiler.compile - end + @compiler.compile + end - it "should accept overrides before the related resource has been created" do - @resource.expects(:merge).with(@override) + it "should accept overrides before the related resource has been created" do + @resource.expects(:merge).with(@override) - # First store the override - @compiler.add_override(@override) + # First store the override + @compiler.add_override(@override) - # Then the resource - @compiler.add_resource(@scope, @resource) + # Then the resource + @compiler.add_resource(@scope, @resource) - # And compile, so they get resolved - @compiler.compile - end + # And compile, so they get resolved + @compiler.compile + end - it "should fail if the compile is finished and resource overrides have not been applied" do - @compiler.add_override(@override) + it "should fail if the compile is finished and resource overrides have not been applied" do + @compiler.add_override(@override) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end end -end -# #620 - Nodes and classes should conflict, else classes don't get evaluated -describe Puppet::Parser::Compiler, "when evaluating nodes and classes with the same name (#620)" do - include CompilerTesting + # #620 - Nodes and classes should conflict, else classes don't get evaluated + describe Puppet::Parser::Compiler, "when evaluating nodes and classes with the same name (#620)" do - before do - @node = stub :nodescope? => true - @class = stub :nodescope? => false - end + before do + @node = stub :nodescope? => true + @class = stub :nodescope? => false + end - it "should fail if a node already exists with the same name as the class being evaluated" do - @compiler.class_set("one", @node) - lambda { @compiler.class_set("one", @class) }.should raise_error(Puppet::ParseError) - end + it "should fail if a node already exists with the same name as the class being evaluated" do + @compiler.class_set("one", @node) + lambda { @compiler.class_set("one", @class) }.should raise_error(Puppet::ParseError) + end - it "should fail if a class already exists with the same name as the node being evaluated" do - @compiler.class_set("one", @class) - lambda { @compiler.class_set("one", @node) }.should raise_error(Puppet::ParseError) + it "should fail if a class already exists with the same name as the node being evaluated" do + @compiler.class_set("one", @class) + lambda { @compiler.class_set("one", @node) }.should raise_error(Puppet::ParseError) + end end -end +end \ No newline at end of file diff --git a/spec/unit/ral/provider/mount.rb b/spec/unit/ral/provider/mount.rb index 65aaf7053..0b90d53c9 100755 --- a/spec/unit/ral/provider/mount.rb +++ b/spec/unit/ral/provider/mount.rb @@ -1,134 +1,130 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/provider/mount' -module MountModuleTesting - def setup +describe Puppet::Provider::Mount do + before :each do @mounter = Object.new @mounter.extend(Puppet::Provider::Mount) @name = "/" @resource = stub 'resource' @resource.stubs(:[]).with(:name).returns(@name) @mounter.stubs(:resource).returns(@resource) end -end -describe Puppet::Provider::Mount, " when mounting" do - include MountModuleTesting + describe Puppet::Provider::Mount, " when mounting" do - it "should use the 'mountcmd' method to mount" do - @mounter.stubs(:options).returns(nil) - @mounter.expects(:mountcmd) + it "should use the 'mountcmd' method to mount" do + @mounter.stubs(:options).returns(nil) + @mounter.expects(:mountcmd) - @mounter.mount - end + @mounter.mount + end - it "should flush before mounting if a flush method exists" do - @mounter.meta_def(:flush) { } - @mounter.expects(:flush) - @mounter.stubs(:mountcmd) - @mounter.stubs(:options).returns(nil) + it "should flush before mounting if a flush method exists" do + @mounter.meta_def(:flush) { } + @mounter.expects(:flush) + @mounter.stubs(:mountcmd) + @mounter.stubs(:options).returns(nil) - @mounter.mount - end + @mounter.mount + end - it "should add the options following '-o' if they exist and are not set to :absent" do - @mounter.stubs(:options).returns("ro") - @mounter.expects(:mountcmd).with { |*ary| ary[0] == "-o" and ary[1] == "ro" } + it "should add the options following '-o' if they exist and are not set to :absent" do + @mounter.stubs(:options).returns("ro") + @mounter.expects(:mountcmd).with { |*ary| ary[0] == "-o" and ary[1] == "ro" } - @mounter.mount - end + @mounter.mount + end - it "should specify the filesystem name to the mount command" do - @mounter.stubs(:options).returns(nil) - @mounter.expects(:mountcmd).with { |*ary| ary[-1] == @name } + it "should specify the filesystem name to the mount command" do + @mounter.stubs(:options).returns(nil) + @mounter.expects(:mountcmd).with { |*ary| ary[-1] == @name } - @mounter.mount + @mounter.mount + end end -end -describe Puppet::Provider::Mount, " when remounting" do - include MountModuleTesting - - it "should use '-o remount' if the resource specifies it supports remounting" do - @mounter.stubs(:info) - @resource.stubs(:[]).with(:remounts).returns(:true) - @mounter.expects(:mountcmd).with("-o", "remount", @name) - @mounter.remount + describe Puppet::Provider::Mount, " when remounting" do + + it "should use '-o remount' if the resource specifies it supports remounting" do + @mounter.stubs(:info) + @resource.stubs(:[]).with(:remounts).returns(:true) + @mounter.expects(:mountcmd).with("-o", "remount", @name) + @mounter.remount + end + + it "should unmount and mount if the resource does not specify it supports remounting" do + @mounter.stubs(:info) + @resource.stubs(:[]).with(:remounts).returns(false) + @mounter.expects(:unmount) + @mounter.expects(:mount) + @mounter.remount + end + + it "should log that it is remounting" do + @resource.stubs(:[]).with(:remounts).returns(:true) + @mounter.stubs(:mountcmd) + @mounter.expects(:info).with("Remounting") + @mounter.remount + end end - it "should unmount and mount if the resource does not specify it supports remounting" do - @mounter.stubs(:info) - @resource.stubs(:[]).with(:remounts).returns(false) - @mounter.expects(:unmount) - @mounter.expects(:mount) - @mounter.remount - end + describe Puppet::Provider::Mount, " when unmounting" do - it "should log that it is remounting" do - @resource.stubs(:[]).with(:remounts).returns(:true) - @mounter.stubs(:mountcmd) - @mounter.expects(:info).with("Remounting") - @mounter.remount + it "should call the :umount command with the resource name" do + @mounter.expects(:umount).with(@name) + @mounter.unmount + end end -end -describe Puppet::Provider::Mount, " when unmounting" do - include MountModuleTesting + describe Puppet::Provider::Mount, " when determining if it is mounted" do - it "should call the :umount command with the resource name" do - @mounter.expects(:umount).with(@name) - @mounter.unmount - end -end - -describe Puppet::Provider::Mount, " when determining if it is mounted" do - include MountModuleTesting + it "should parse the results of running the mount command with no arguments" do + Facter.stubs(:value).returns("whatever") + @mounter.expects(:mountcmd).returns("") - it "should parse the results of running the mount command with no arguments" do - Facter.stubs(:value).returns("whatever") - @mounter.expects(:mountcmd).returns("") - - @mounter.mounted? - end + @mounter.mounted? + end - it "should match ' on /private/var/automount' if the operating system is Darwin" do - Facter.stubs(:value).with("operatingsystem").returns("Darwin") - @mounter.expects(:mountcmd).returns("/dev/whatever on /private/var/automount/\ndevfs on /dev") + it "should match ' on /private/var/automount' if the operating system is Darwin" do + Facter.stubs(:value).with("operatingsystem").returns("Darwin") + @mounter.expects(:mountcmd).returns("/dev/whatever on /private/var/automount/\ndevfs on /dev") - @mounter.should be_mounted - end + @mounter.should be_mounted + end - it "should match ' on ' if the operating system is Darwin" do - Facter.stubs(:value).with("operatingsystem").returns("Darwin") - @mounter.expects(:mountcmd).returns("/dev/disk03 on / (local, journaled)\ndevfs on /dev") + it "should match ' on ' if the operating system is Darwin" do + Facter.stubs(:value).with("operatingsystem").returns("Darwin") + @mounter.expects(:mountcmd).returns("/dev/disk03 on / (local, journaled)\ndevfs on /dev") - @mounter.should be_mounted - end + @mounter.should be_mounted + end - it "should match '^ on' if the operating system is Solaris" do - Facter.stubs(:value).with("operatingsystem").returns("Solaris") - @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other") + it "should match '^ on' if the operating system is Solaris" do + Facter.stubs(:value).with("operatingsystem").returns("Solaris") + @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other") - @mounter.should be_mounted - end + @mounter.should be_mounted + end - it "should match ' on ' if the operating system is not Darwin or Solaris" do - Facter.stubs(:value).with("operatingsystem").returns("Debian") - @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff") + it "should match ' on ' if the operating system is not Darwin or Solaris" do + Facter.stubs(:value).with("operatingsystem").returns("Debian") + @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff") - @mounter.should be_mounted - end + @mounter.should be_mounted + end - it "should not be considered mounted if it did not match the mount output" do - Facter.stubs(:value).with("operatingsystem").returns("Debian") - @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on /something/else and stuff\n/dev/other/disk on /var and stuff") + it "should not be considered mounted if it did not match the mount output" do + Facter.stubs(:value).with("operatingsystem").returns("Debian") + @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on /something/else and stuff\n/dev/other/disk on /var and stuff") - @mounter.should_not be_mounted + @mounter.should_not be_mounted + end end end diff --git a/spec/unit/ral/provider/mount/parsed.rb b/spec/unit/ral/provider/mount/parsed.rb index 89928891a..b2ca22987 100755 --- a/spec/unit/ral/provider/mount/parsed.rb +++ b/spec/unit/ral/provider/mount/parsed.rb @@ -1,182 +1,185 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-12. # Copyright (c) 2006. All rights reserved. require File.dirname(__FILE__) + '/../../../../spec_helper' require 'puppettest/support/utils' require 'puppettest/fileparsing' module ParsedMountTesting include PuppetTest::Support::Utils include PuppetTest::FileParsing - def setup - @mount_class = Puppet.type(:mount) - @provider_class = @mount_class.provider(:parsed) - end - def fake_fstab os = Facter['operatingsystem'] if os == "Solaris" name = "solaris.fstab" elsif os == "FreeBSD" name = "freebsd.fstab" else # Catchall for other fstabs name = "linux.fstab" end oldpath = @provider_class.default_target return fakefile(File::join("data/types/mount", name)) end def mkmountargs mount = nil if defined? @pcount @pcount += 1 else @pcount = 1 end args = { :name => "/fspuppet%s" % @pcount, :device => "/dev/dsk%s" % @pcount, } @provider_class.fields(:parsed).each do |field| unless args.include? field args[field] = "fake%s%s" % [field, @pcount] end end return args end def mkmount hash = mkmountargs() #hash[:provider] = @provider_class.name fakeresource = stub :type => :mount, :name => hash[:name] fakeresource.stubs(:[]).with(:name).returns(hash[:name]) fakeresource.stubs(:should).with(:target).returns(nil) mount = @provider_class.new(fakeresource) hash[:record_type] = :parsed hash[:ensure] = :present mount.property_hash = hash return mount end # Here we just create a fake host type that answers to all of the methods # but does not modify our actual system. def mkfaketype @provider.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) end end provider_class = Puppet::Type.type(:mount).provider(:parsed) describe provider_class do - include ParsedMountTesting + before :each do + @mount_class = Puppet.type(:mount) + @provider_class = @mount_class.provider(:parsed) + end - it "should be able to parse all of the example mount tabs" do - tab = fake_fstab - @provider = @provider_class - # LAK:FIXME Again, a relatively bad test, but I don't know how to rspec-ify this. - # I suppose this is more of an integration test? I dunno. - fakedataparse(tab) do - # Now just make we've got some mounts we know will be there - hashes = @provider_class.target_records(tab).find_all { |i| i.is_a? Hash } - (hashes.length > 0).should be_true - root = hashes.find { |i| i[:name] == "/" } + describe provider_class do + include ParsedMountTesting - proc { @provider_class.to_file(hashes) }.should_not raise_error - end - end + it "should be able to parse all of the example mount tabs" do + tab = fake_fstab + @provider = @provider_class + + # LAK:FIXME Again, a relatively bad test, but I don't know how to rspec-ify this. + # I suppose this is more of an integration test? I dunno. + fakedataparse(tab) do + # Now just make we've got some mounts we know will be there + hashes = @provider_class.target_records(tab).find_all { |i| i.is_a? Hash } + (hashes.length > 0).should be_true + root = hashes.find { |i| i[:name] == "/" } - # LAK:FIXME I can't mock Facter because this test happens at parse-time. - it "should default to /etc/vfstab on Solaris and /etc/fstab everywhere else" do - should = case Facter.value(:operatingsystem) - when "Solaris": "/etc/vfstab" - else - "/etc/fstab" + proc { @provider_class.to_file(hashes) }.should_not raise_error end - Puppet::Type.type(:mount).provider(:parsed).default_target.should == should + end + + # LAK:FIXME I can't mock Facter because this test happens at parse-time. + it "should default to /etc/vfstab on Solaris and /etc/fstab everywhere else" do + should = case Facter.value(:operatingsystem) + when "Solaris": "/etc/vfstab" + else + "/etc/fstab" + end + Puppet::Type.type(:mount).provider(:parsed).default_target.should == should + end end -end -describe provider_class, " when mounting an absent filesystem" do - include ParsedMountTesting + describe provider_class, " when mounting an absent filesystem" do + include ParsedMountTesting - # #730 - Make sure 'flush' is called when a mount is moving from absent to mounted - it "should flush the fstab to disk" do - mount = mkmount + # #730 - Make sure 'flush' is called when a mount is moving from absent to mounted + it "should flush the fstab to disk" do + mount = mkmount - # Mark the mount as absent - mount.property_hash[:ensure] = :absent + # Mark the mount as absent + mount.property_hash[:ensure] = :absent - mount.stubs(:mountcmd) # just so we don't actually try to mount anything + mount.stubs(:mountcmd) # just so we don't actually try to mount anything - mount.expects(:flush) - mount.mount + mount.expects(:flush) + mount.mount + end end -end -describe provider_class, " when modifying the filesystem tab" do - include ParsedMountTesting - before do - @mount = mkmount - @target = @provider_class.default_target + describe provider_class, " when modifying the filesystem tab" do + include ParsedMountTesting + before do + @mount = mkmount + @target = @provider_class.default_target - # Never write to disk, only to RAM. - @provider_class.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) - end + # Never write to disk, only to RAM. + @provider_class.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) + end - it "should write the mount to disk when :flush is called" do - @mount.flush + it "should write the mount to disk when :flush is called" do + @mount.flush - text = @provider_class.target_object(@provider_class.default_target).read - text.should == @mount.class.to_line(@mount.property_hash) + "\n" + text = @provider_class.target_object(@provider_class.default_target).read + text.should == @mount.class.to_line(@mount.property_hash) + "\n" + end end -end -describe provider_class, " when parsing information about the root filesystem" do - confine "Mount type not tested on Darwin" => Facter["operatingsystem"].value != "Darwin" - include ParsedMountTesting + describe provider_class, " when parsing information about the root filesystem" do + confine "Mount type not tested on Darwin" => Facter["operatingsystem"].value != "Darwin" + include ParsedMountTesting - before do - @mount = @mount_class.create :name => "/" - @provider = @mount.provider - end + before do + @mount = @mount_class.create :name => "/" + @provider = @mount.provider + end - it "should have a filesystem tab" do - FileTest.should be_exist(@provider_class.default_target) - end + it "should have a filesystem tab" do + FileTest.should be_exist(@provider_class.default_target) + end - it "should find the root filesystem" do - @provider_class.prefetch("/" => @mount) - @mount.provider.property_hash[:ensure].should == :present - end + it "should find the root filesystem" do + @provider_class.prefetch("/" => @mount) + @mount.provider.property_hash[:ensure].should == :present + end - it "should determine that the root fs is mounted" do - @provider_class.prefetch("/" => @mount) - @mount.provider.should be_mounted - end + it "should determine that the root fs is mounted" do + @provider_class.prefetch("/" => @mount) + @mount.provider.should be_mounted + end - after do - Puppet::Type.allclear + after do + Puppet::Type.allclear + end end -end -describe provider_class, " when mounting and unmounting" do - include ParsedMountTesting + describe provider_class, " when mounting and unmounting" do + include ParsedMountTesting - it "should call the 'mount' command to mount the filesystem" + it "should call the 'mount' command to mount the filesystem" - it "should call the 'unmount' command to unmount the filesystem" + it "should call the 'unmount' command to unmount the filesystem" - it "should specify the filesystem when remounting a filesystem" -end + it "should specify the filesystem when remounting a filesystem" + end +end \ No newline at end of file diff --git a/spec/unit/ral/types/mount.rb b/spec/unit/ral/types/mount.rb index 7d01022b5..9247601e6 100755 --- a/spec/unit/ral/types/mount.rb +++ b/spec/unit/ral/types/mount.rb @@ -1,195 +1,192 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/type/mount' describe Puppet::Type::Mount do it "should have a :refreshable feature that requires the :remount method" do Puppet::Type::Mount.provider_feature(:refreshable).methods.should == [:remount] end it "should have no default value for :ensure" do mount = Puppet::Type::Mount.create(:name => "yay") mount.should(:ensure).should be_nil end after { Puppet::Type::Mount.clear } end describe Puppet::Type::Mount, "when validating attributes" do [:name, :remounts].each do |param| it "should have a #{param} parameter" do Puppet::Type::Mount.attrtype(param).should == :param end end [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param| it "should have a #{param} property" do Puppet::Type::Mount.attrtype(param).should == :property end end end describe Puppet::Type::Mount::Ensure, "when validating values" do before do @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil Puppet::Type::Mount.defaultprovider.expects(:new).returns(@provider) end it "should support :present as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :present) end it "should alias :unmounted to :present as a value to :ensure" do mount = Puppet::Type::Mount.create(:name => "yay", :ensure => :unmounted) mount.should(:ensure).should == :present end it "should support :absent as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :absent) end it "should support :mounted as a value to :ensure" do Puppet::Type::Mount.create(:name => "yay", :ensure => :mounted) end after { Puppet::Type::Mount.clear } end -module MountEvaluationTesting - def setup +describe Puppet::Type::Mount::Ensure do + before :each do @provider = stub 'provider', :class => Puppet::Type::Mount.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock Puppet::Type::Mount.defaultprovider.stubs(:new).returns(@provider) @mount = Puppet::Type::Mount.create(:name => "yay", :check => :ensure) @ensure = @mount.property(:ensure) end + after :each do + Puppet::Type::Mount.clear + end + def mount_stub(params) Puppet::Type::Mount.validproperties.each do |prop| unless params[prop] params[prop] = :absent @mount[prop] = :absent end end params.each do |param, value| @provider.stubs(param).returns(value) end end - def teardown - Puppet::Type::Mount.clear - end -end - -describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do - include MountEvaluationTesting + describe Puppet::Type::Mount::Ensure, "when retrieving its current state" do - it "should return the provider's value if it is :absent" do - @provider.expects(:ensure).returns(:absent) - @ensure.retrieve.should == :absent - end + it "should return the provider's value if it is :absent" do + @provider.expects(:ensure).returns(:absent) + @ensure.retrieve.should == :absent + end - it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do - @provider.expects(:ensure).returns(:present) - @provider.expects(:mounted?).returns(true) - @ensure.retrieve.should == :mounted - end + it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do + @provider.expects(:ensure).returns(:present) + @provider.expects(:mounted?).returns(true) + @ensure.retrieve.should == :mounted + end - it "should return :present if the provider indicates it is not mounted and the value is not :absent" do - @provider.expects(:ensure).returns(:present) - @provider.expects(:mounted?).returns(false) - @ensure.retrieve.should == :present + it "should return :present if the provider indicates it is not mounted and the value is not :absent" do + @provider.expects(:ensure).returns(:present) + @provider.expects(:mounted?).returns(false) + @ensure.retrieve.should == :present + end end -end -describe Puppet::Type::Mount::Ensure, "when changing the host" do - include MountEvaluationTesting + describe Puppet::Type::Mount::Ensure, "when changing the host" do - it "should destroy itself if it should be absent" do - @provider.stubs(:mounted?).returns(false) - @provider.expects(:destroy) - @ensure.should = :absent - @ensure.sync - end + it "should destroy itself if it should be absent" do + @provider.stubs(:mounted?).returns(false) + @provider.expects(:destroy) + @ensure.should = :absent + @ensure.sync + end - it "should unmount itself before destroying if it is mounted and should be absent" do - @provider.expects(:mounted?).returns(true) - @provider.expects(:unmount) - @provider.expects(:destroy) - @ensure.should = :absent - @ensure.sync - end + it "should unmount itself before destroying if it is mounted and should be absent" do + @provider.expects(:mounted?).returns(true) + @provider.expects(:unmount) + @provider.expects(:destroy) + @ensure.should = :absent + @ensure.sync + end - it "should create itself if it is absent and should be present" do - @provider.stubs(:mounted?).returns(false) - @provider.expects(:create) - @ensure.should = :present - @ensure.sync - end + it "should create itself if it is absent and should be present" do + @provider.stubs(:mounted?).returns(false) + @provider.expects(:create) + @ensure.should = :present + @ensure.sync + end - it "should unmount itself if it is mounted and should be present" do - @provider.stubs(:mounted?).returns(true) + it "should unmount itself if it is mounted and should be present" do + @provider.stubs(:mounted?).returns(true) - # The interface here is just too much work to test right now. - @ensure.stubs(:syncothers) - @provider.expects(:unmount) - @ensure.should = :present - @ensure.sync - end + # The interface here is just too much work to test right now. + @ensure.stubs(:syncothers) + @provider.expects(:unmount) + @ensure.should = :present + @ensure.sync + end - it "should create and mount itself if it does not exist and should be mounted" do - @provider.stubs(:ensure).returns(:absent) - @provider.stubs(:mounted?).returns(false) - @provider.expects(:create) - @ensure.stubs(:syncothers) - @provider.expects(:mount) - @ensure.should = :mounted - @ensure.sync - end + it "should create and mount itself if it does not exist and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(false) + @provider.expects(:create) + @ensure.stubs(:syncothers) + @provider.expects(:mount) + @ensure.should = :mounted + @ensure.sync + end - it "should mount itself if it is present and should be mounted" do - @provider.stubs(:ensure).returns(:present) - @provider.stubs(:mounted?).returns(false) - @ensure.stubs(:syncothers) - @provider.expects(:mount) - @ensure.should = :mounted - @ensure.sync - end + it "should mount itself if it is present and should be mounted" do + @provider.stubs(:ensure).returns(:present) + @provider.stubs(:mounted?).returns(false) + @ensure.stubs(:syncothers) + @provider.expects(:mount) + @ensure.should = :mounted + @ensure.sync + end - it "should create but not mount itself if it is absent and mounted and should be mounted" do - @provider.stubs(:ensure).returns(:absent) - @provider.stubs(:mounted?).returns(true) - @ensure.stubs(:syncothers) - @provider.expects(:create) - @ensure.should = :mounted - @ensure.sync + it "should create but not mount itself if it is absent and mounted and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(true) + @ensure.stubs(:syncothers) + @provider.expects(:create) + @ensure.should = :mounted + @ensure.sync + end end -end -describe Puppet::Type::Mount, "when responding to events" do - include MountEvaluationTesting + describe Puppet::Type::Mount, "when responding to events" do - it "should remount if it is currently mounted" do - @provider.expects(:mounted?).returns(true) - @provider.expects(:remount) + it "should remount if it is currently mounted" do + @provider.expects(:mounted?).returns(true) + @provider.expects(:remount) - @mount.refresh - end + @mount.refresh + end - it "should not remount if it is not currently mounted" do - @provider.expects(:mounted?).returns(false) - @provider.expects(:remount).never + it "should not remount if it is not currently mounted" do + @provider.expects(:mounted?).returns(false) + @provider.expects(:remount).never - @mount.refresh - end + @mount.refresh + end - it "should not remount swap filesystems" do - @mount[:fstype] = "swap" - @provider.expects(:remount).never + it "should not remount swap filesystems" do + @mount[:fstype] = "swap" + @provider.expects(:remount).never - @mount.refresh + @mount.refresh + end end -end +end \ No newline at end of file diff --git a/spec/unit/ral/types/package.rb b/spec/unit/ral/types/package.rb index f14a792b9..785d2eb37 100755 --- a/spec/unit/ral/types/package.rb +++ b/spec/unit/ral/types/package.rb @@ -1,244 +1,247 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/type/package' describe Puppet::Type::Package do it "should have an :installable feature that requires the :install method" do Puppet::Type::Package.provider_feature(:installable).methods.should == [:install] end it "should have an :uninstallable feature that requires the :uninstall method" do Puppet::Type::Package.provider_feature(:uninstallable).methods.should == [:uninstall] end it "should have an :upgradeable feature that requires :update and :latest methods" do Puppet::Type::Package.provider_feature(:upgradeable).methods.should == [:update, :latest] end it "should have a :purgeable feature that requires the :purge latest method" do Puppet::Type::Package.provider_feature(:purgeable).methods.should == [:purge] end it "should have a :versionable feature" do Puppet::Type::Package.provider_feature(:versionable).should_not be_nil end it "should default to being installed" do pkg = Puppet::Type::Package.create(:name => "yay") pkg.should(:ensure).should == :present end after { Puppet::Type::Package.clear } end describe Puppet::Type::Package, "when validating attributes" do [:name, :source, :instance, :status, :adminfile, :responsefile, :configfiles, :category, :platform, :root, :vendor, :description, :allowcdrom].each do |param| it "should have a #{param} parameter" do Puppet::Type::Package.attrtype(param).should == :param end end it "should have an ensure property" do Puppet::Type::Package.attrtype(:ensure).should == :property end end describe Puppet::Type::Package, "when validating attribute values" do before do @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil Puppet::Type::Package.defaultprovider.expects(:new).returns(@provider) end it "should support :present as a value to :ensure" do Puppet::Type::Package.create(:name => "yay", :ensure => :present) end it "should alias :installed to :present as a value to :ensure" do pkg = Puppet::Type::Package.create(:name => "yay", :ensure => :installed) pkg.should(:ensure).should == :present end it "should support :absent as a value to :ensure" do Puppet::Type::Package.create(:name => "yay", :ensure => :absent) end it "should support :purged as a value to :ensure if the provider has the :purgeable feature" do @provider.expects(:satisfies?).with(:purgeable).returns(true) Puppet::Type::Package.create(:name => "yay", :ensure => :purged) end it "should not support :purged as a value to :ensure if the provider does not have the :purgeable feature" do @provider.expects(:satisfies?).with(:purgeable).returns(false) proc { Puppet::Type::Package.create(:name => "yay", :ensure => :purged) }.should raise_error(Puppet::Error) end it "should support :latest as a value to :ensure if the provider has the :upgradeable feature" do @provider.expects(:satisfies?).with(:upgradeable).returns(true) Puppet::Type::Package.create(:name => "yay", :ensure => :latest) end it "should not support :latest as a value to :ensure if the provider does not have the :upgradeable feature" do @provider.expects(:satisfies?).with(:upgradeable).returns(false) proc { Puppet::Type::Package.create(:name => "yay", :ensure => :latest) }.should raise_error(Puppet::Error) end it "should support version numbers as a value to :ensure if the provider has the :versionable feature" do @provider.expects(:satisfies?).with(:versionable).returns(true) Puppet::Type::Package.create(:name => "yay", :ensure => "1.0") end it "should not support version numbers as a value to :ensure if the provider does not have the :versionable feature" do @provider.expects(:satisfies?).with(:versionable).returns(false) proc { Puppet::Type::Package.create(:name => "yay", :ensure => "1.0") }.should raise_error(Puppet::Error) end it "should only accept files and URLs as values to :source" do proc { Puppet::Type::Package.create(:name => "yay", :source => "stuff") }.should raise_error(Puppet::Error) end after { Puppet::Type::Package.clear } end module PackageEvaluationTesting - def setup + def setprops(properties) + @provider.stubs(:properties).returns(properties) + end +end + +describe Puppet::Type::Package do + before :each do @provider = stub 'provider', :class => Puppet::Type::Package.defaultprovider, :clear => nil, :satisfies? => true, :name => :mock Puppet::Type::Package.defaultprovider.stubs(:new).returns(@provider) @package = Puppet::Type::Package.create(:name => "yay") @catalog = Puppet::Node::Catalog.new @catalog.add_resource(@package) end - - def setprops(properties) - @provider.stubs(:properties).returns(properties) - end - - def teardown + + after :each do @catalog.clear(true) Puppet::Type::Package.clear end -end -describe Puppet::Type::Package, "when it should be purged" do - include PackageEvaluationTesting - before { @package[:ensure] = :purged } + describe Puppet::Type::Package, "when it should be purged" do + include PackageEvaluationTesting - it "should do nothing if it is :purged" do - @provider.expects(:properties).returns(:ensure => :purged) - @catalog.apply - end + before { @package[:ensure] = :purged } - [:absent, :installed, :present, :latest].each do |state| - it "should purge if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:purge) + it "should do nothing if it is :purged" do + @provider.expects(:properties).returns(:ensure => :purged) @catalog.apply end + + [:absent, :installed, :present, :latest].each do |state| + it "should purge if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:purge) + @catalog.apply + end + end end -end -describe Puppet::Type::Package, "when it should be absent" do - include PackageEvaluationTesting + describe Puppet::Type::Package, "when it should be absent" do + include PackageEvaluationTesting - before { @package[:ensure] = :absent } + before { @package[:ensure] = :absent } - [:purged, :absent].each do |state| - it "should do nothing if it is #{state.to_s}" do - @provider.expects(:properties).returns(:ensure => state) - @catalog.apply + [:purged, :absent].each do |state| + it "should do nothing if it is #{state.to_s}" do + @provider.expects(:properties).returns(:ensure => state) + @catalog.apply + end end - end - [:installed, :present, :latest].each do |state| - it "should uninstall if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:uninstall) - @catalog.apply + [:installed, :present, :latest].each do |state| + it "should uninstall if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:uninstall) + @catalog.apply + end end end -end -describe Puppet::Type::Package, "when it should be present" do - include PackageEvaluationTesting + describe Puppet::Type::Package, "when it should be present" do + include PackageEvaluationTesting - before { @package[:ensure] = :present } + before { @package[:ensure] = :present } - [:present, :latest, "1.0"].each do |state| - it "should do nothing if it is #{state.to_s}" do - @provider.expects(:properties).returns(:ensure => state) - @catalog.apply + [:present, :latest, "1.0"].each do |state| + it "should do nothing if it is #{state.to_s}" do + @provider.expects(:properties).returns(:ensure => state) + @catalog.apply + end end - end - [:purged, :absent].each do |state| - it "should install if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:install) - @catalog.apply + [:purged, :absent].each do |state| + it "should install if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:install) + @catalog.apply + end end end -end -describe Puppet::Type::Package, "when it should be latest" do - include PackageEvaluationTesting + describe Puppet::Type::Package, "when it should be latest" do + include PackageEvaluationTesting - before { @package[:ensure] = :latest } + before { @package[:ensure] = :latest } - [:purged, :absent].each do |state| - it "should upgrade if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) + [:purged, :absent].each do |state| + it "should upgrade if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:update) + @catalog.apply + end + end + + it "should upgrade if the current version is not equal to the latest version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.stubs(:latest).returns("2.0") @provider.expects(:update) @catalog.apply end - end - it "should upgrade if the current version is not equal to the latest version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.stubs(:latest).returns("2.0") - @provider.expects(:update) - @catalog.apply - end + it "should do nothing if it is equal to the latest version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.stubs(:latest).returns("1.0") + @provider.expects(:update).never + @catalog.apply + end - it "should do nothing if it is equal to the latest version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.stubs(:latest).returns("1.0") - @provider.expects(:update).never - @catalog.apply + it "should do nothing if the provider returns :present as the latest version" do + @provider.stubs(:properties).returns(:ensure => :present) + @provider.stubs(:latest).returns("1.0") + @provider.expects(:update).never + @catalog.apply + end end - it "should do nothing if the provider returns :present as the latest version" do - @provider.stubs(:properties).returns(:ensure => :present) - @provider.stubs(:latest).returns("1.0") - @provider.expects(:update).never - @catalog.apply - end -end + describe Puppet::Type::Package, "when it should be a specific version" do + include PackageEvaluationTesting -describe Puppet::Type::Package, "when it should be a specific version" do - include PackageEvaluationTesting + before { @package[:ensure] = "1.0" } - before { @package[:ensure] = "1.0" } + [:purged, :absent].each do |state| + it "should install if it is #{state.to_s}" do + @provider.stubs(:properties).returns(:ensure => state) + @provider.expects(:install) + @catalog.apply + end + end - [:purged, :absent].each do |state| - it "should install if it is #{state.to_s}" do - @provider.stubs(:properties).returns(:ensure => state) - @provider.expects(:install) + it "should do nothing if the current version is equal to the desired version" do + @provider.stubs(:properties).returns(:ensure => "1.0") + @provider.expects(:install).never @catalog.apply end - end - it "should do nothing if the current version is equal to the desired version" do - @provider.stubs(:properties).returns(:ensure => "1.0") - @provider.expects(:install).never - @catalog.apply - end - - it "should install if the current version is not equal to the specified version" do - @provider.stubs(:properties).returns(:ensure => "2.0") - @provider.expects(:install) - @catalog.apply + it "should install if the current version is not equal to the specified version" do + @provider.stubs(:properties).returns(:ensure => "2.0") + @provider.expects(:install) + @catalog.apply + end end end diff --git a/spec/unit/ral/types/schedule.rb b/spec/unit/ral/types/schedule.rb index 73b3a0bd1..4e9840c34 100755 --- a/spec/unit/ral/types/schedule.rb +++ b/spec/unit/ral/types/schedule.rb @@ -1,374 +1,341 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppet/type/schedule' module ScheduleTesting - def setup - Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) - - @schedule = Puppet::Type::Schedule.create(:name => "testing") - end def format(time) time.strftime("%H:%M:%S") end def diff(unit, incr, method, count) diff = Time.now.to_i.send(method, incr * count) Time.at(diff) end def month(method, count) diff(:hour, 3600 * 24 * 30, method, count) end def week(method, count) diff(:hour, 3600 * 24 * 7, method, count) end def day(method, count) diff(:hour, 3600 * 24, method, count) end def hour(method, count) diff(:hour, 3600, method, count) end def min(method, count) diff(:min, 60, method, count) end def sec(method, count) diff(:sec, 1, method, count) end - def teardown - Puppet::Type::Schedule.clear - end end describe Puppet::Type::Schedule do - include ScheduleTesting - - it "should default to :distance for period-matching" do - @schedule[:periodmatch].should == :distance - end - it "should default to a :repeat of 1" do - @schedule[:repeat].should == 1 - end - - it "should never match when the period is :never" do - @schedule[:period] = :never - @schedule.match?.should be_false - end -end - -describe Puppet::Type::Schedule, "when producing default schedules" do - include ScheduleTesting + before :each do + Puppet.settings.stubs(:value).with(:ignoreschedules).returns(false) - %w{hourly daily weekly monthly never}.each do |period| - period = period.to_sym - it "should produce a #{period} schedule with the period set appropriately" do - schedules = Puppet::Type::Schedule.mkdefaultschedules - schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type::Schedule) - end + @schedule = Puppet::Type::Schedule.create(:name => "testing") end - it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do - schedules = Puppet::Type::Schedule.mkdefaultschedules - schedules.find { |s| - s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 - }.should be_instance_of(Puppet::Type::Schedule) + after :each do + Puppet::Type::Schedule.clear end -end -describe Puppet::Type::Schedule, "when matching ranges" do - include ScheduleTesting - it "should match when the start time is before the current time and the end time is after the current time" do - @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)] - @schedule.match?.should be_true - end - - it "should not match when the start time is after the current time" do - @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)] - @schedule.match?.should be_false - end + describe Puppet::Type::Schedule do + include ScheduleTesting - it "should not match when the end time is previous to the current time" do - @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)] - @schedule.match?.should be_false - end -end + it "should default to :distance for period-matching" do + @schedule[:periodmatch].should == :distance + end -describe Puppet::Type::Schedule, "when matching hourly by distance" do - include ScheduleTesting + it "should default to a :repeat of 1" do + @schedule[:repeat].should == 1 + end - before do - @schedule[:period] = :hourly - @schedule[:periodmatch] = :distance + it "should never match when the period is :never" do + @schedule[:period] = :never + @schedule.match?.should be_false + end end - it "should match an hour ago" do - @schedule.match?(hour("-", 1)).should be_true - end + describe Puppet::Type::Schedule, "when producing default schedules" do + include ScheduleTesting - it "should not match now" do - @schedule.match?(Time.now).should be_false - end + %w{hourly daily weekly monthly never}.each do |period| + period = period.to_sym + it "should produce a #{period} schedule with the period set appropriately" do + schedules = Puppet::Type::Schedule.mkdefaultschedules + schedules.find { |s| s[:name] == period.to_s and s[:period] == period }.should be_instance_of(Puppet::Type::Schedule) + end + end - it "should not match 59 minutes ago" do - @schedule.match?(min("-", 59)).should be_false + it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do + schedules = Puppet::Type::Schedule.mkdefaultschedules + schedules.find { |s| + s[:name] == "puppet" and s[:period] == :hourly and s[:repeat] == 2 + }.should be_instance_of(Puppet::Type::Schedule) + end end -end - -describe Puppet::Type::Schedule, "when matching daily by distance" do - include ScheduleTesting - before do - @schedule[:period] = :daily - @schedule[:periodmatch] = :distance - end + describe Puppet::Type::Schedule, "when matching ranges" do + include ScheduleTesting - it "should match when the previous time was one day ago" do - @schedule.match?(day("-", 1)).should be_true - end + it "should match when the start time is before the current time and the end time is after the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now + 10)] + @schedule.match?.should be_true + end - it "should not match when the previous time is now" do - @schedule.match?(Time.now).should be_false - end + it "should not match when the start time is after the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now + 5), format(Time.now + 10)] + @schedule.match?.should be_false + end - it "should not match when the previous time was 23 hours ago" do - @schedule.match?(hour("-", 23)).should be_false + it "should not match when the end time is previous to the current time" do + @schedule[:range] = "%s - %s" % [format(Time.now - 10), format(Time.now - 5)] + @schedule.match?.should be_false + end end -end -describe Puppet::Type::Schedule, "when matching weekly by distance" do - include ScheduleTesting + describe Puppet::Type::Schedule, "when matching hourly by distance" do + include ScheduleTesting - before do - @schedule[:period] = :weekly - @schedule[:periodmatch] = :distance - end + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :distance + end - it "should match seven days ago" do - @schedule.match?(day("-", 7)).should be_true - end + it "should match an hour ago" do + @schedule.match?(hour("-", 1)).should be_true + end - it "should not match now" do - @schedule.match?(Time.now).should be_false - end + it "should not match now" do + @schedule.match?(Time.now).should be_false + end - it "should not match six days ago" do - @schedule.match?(day("-", 6)).should be_false + it "should not match 59 minutes ago" do + @schedule.match?(min("-", 59)).should be_false + end end -end -describe Puppet::Type::Schedule, "when matching monthly by distance" do - include ScheduleTesting + describe Puppet::Type::Schedule, "when matching daily by distance" do + include ScheduleTesting - before do - @schedule[:period] = :monthly - @schedule[:periodmatch] = :distance - end + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :distance + end - it "should match 32 days ago" do - @schedule.match?(day("-", 32)).should be_true - end + it "should match when the previous time was one day ago" do + @schedule.match?(day("-", 1)).should be_true + end - it "should not match now" do - @schedule.match?(Time.now).should be_false - end + it "should not match when the previous time is now" do + @schedule.match?(Time.now).should be_false + end - it "should not match 27 days ago" do - @schedule.match?(day("-", 27)).should be_false + it "should not match when the previous time was 23 hours ago" do + @schedule.match?(hour("-", 23)).should be_false + end end -end -describe Puppet::Type::Schedule, "when matching hourly by number" do - include ScheduleTesting + describe Puppet::Type::Schedule, "when matching weekly by distance" do + include ScheduleTesting - before do - @schedule[:period] = :hourly - @schedule[:periodmatch] = :number - end + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :distance + end - it "should match if the times are one minute apart and the current minute is 0" do - current = Time.now + it "should match seven days ago" do + @schedule.match?(day("-", 7)).should be_true + end - # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes. - previous = (current - 3600 - (current.min * 60) + (59 * 60)) + it "should not match now" do + @schedule.match?(Time.now).should be_false + end - # Now set the "current" time to the zero minute of the current hour. - now = (current - (current.min * 60)) - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_true + it "should not match six days ago" do + @schedule.match?(day("-", 6)).should be_false + end end - it "should not match if the times are 58 minutes apart and the current minute is 59" do - current = Time.now + describe Puppet::Type::Schedule, "when matching monthly by distance" do + include ScheduleTesting - # reset the minute to zero - previous = current - (current.min * 60) + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :distance + end - # Now set the "current" time to the 59th minute of the current hour. - now = (current - (current.min * 60) + (59 * 60)) - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_false - end -end + it "should match 32 days ago" do + @schedule.match?(day("-", 32)).should be_true + end -describe Puppet::Type::Schedule, "when matching daily by number" do - include ScheduleTesting + it "should not match now" do + @schedule.match?(Time.now).should be_false + end - before do - @schedule[:period] = :daily - @schedule[:periodmatch] = :number + it "should not match 27 days ago" do + @schedule.match?(day("-", 27)).should be_false + end end - it "should match if the times are one minute apart and the current minute and hour are 0" do - zero = Time.now + describe Puppet::Type::Schedule, "when matching hourly by number" do + include ScheduleTesting - # Reset the current time to X:00:00 - current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + before do + @schedule[:period] = :hourly + @schedule[:periodmatch] = :number + end - # Now set the previous time to one minute before that - previous = current - 60 + it "should match if the times are one minute apart and the current minute is 0" do + current = Time.now - Time.stubs(:now).returns(current) - @schedule.match?(previous).should be_true - end + # Subtract an hour, reset the minute to zero, then add 59 minutes, so we're the previous hour plus 59 minutes. + previous = (current - 3600 - (current.min * 60) + (59 * 60)) - it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do - zero = Time.now + # Now set the "current" time to the zero minute of the current hour. + now = (current - (current.min * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_true + end - # Reset the previous time to 00:00:00 - previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec + it "should not match if the times are 58 minutes apart and the current minute is 59" do + current = Time.now - # Set the current time to 23:59 - now = previous + (23 * 3600) + (59 * 60) + # reset the minute to zero + previous = current - (current.min * 60) - Time.stubs(:now).returns(now) - @schedule.match?(previous).should be_false + # Now set the "current" time to the 59th minute of the current hour. + now = (current - (current.min * 60) + (59 * 60)) + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end end -end -describe Puppet::Type::Schedule, "when matching weekly by number" do - include ScheduleTesting + describe Puppet::Type::Schedule, "when matching daily by number" do + include ScheduleTesting - before do - @schedule[:period] = :weekly - @schedule[:periodmatch] = :number - end + before do + @schedule[:period] = :daily + @schedule[:periodmatch] = :number + end - it "should match if the previous time is prior to the most recent Sunday" do - now = Time.now + it "should match if the times are one minute apart and the current minute and hour are 0" do + zero = Time.now - # Subtract the number days we've progressed into the week, plus one because we're zero-indexed. - previous = now - (3600 * 24 * (now.wday + 1)) + # Reset the current time to X:00:00 + current = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec - @schedule.match?(previous).should be_true - end + # Now set the previous time to one minute before that + previous = current - 60 - it "should not match if the previous time is after the most recent Saturday" do - now = Time.now + Time.stubs(:now).returns(current) + @schedule.match?(previous).should be_true + end - # Subtract the number days we've progressed into the week - previous = now - (3600 * 24 * now.wday) + it "should not match if the times are 23 hours and 58 minutes apart and the current hour is 23 and the current minute is 59" do + zero = Time.now - @schedule.match?(previous).should be_false - end -end + # Reset the previous time to 00:00:00 + previous = zero - (zero.hour * 3600) - (zero.min * 60) - zero.sec -describe Puppet::Type::Schedule, "when matching monthly by number" do - include ScheduleTesting + # Set the current time to 23:59 + now = previous + (23 * 3600) + (59 * 60) - before do - @schedule[:period] = :monthly - @schedule[:periodmatch] = :number + Time.stubs(:now).returns(now) + @schedule.match?(previous).should be_false + end end - it "should match when the previous time is prior to the first day of this month" do - now = Time.now + describe Puppet::Type::Schedule, "when matching weekly by number" do + include ScheduleTesting - # Subtract the number days we've progressed into the month - previous = now - (3600 * 24 * now.day) + before do + @schedule[:period] = :weekly + @schedule[:periodmatch] = :number + end - @schedule.match?(previous).should be_true - end + it "should match if the previous time is prior to the most recent Sunday" do + now = Time.now - it "should not match when the previous time is after the last day of last month" do - now = Time.now + # Subtract the number days we've progressed into the week, plus one because we're zero-indexed. + previous = now - (3600 * 24 * (now.wday + 1)) - # Subtract the number days we've progressed into the month, minus one - previous = now - (3600 * 24 * (now.day - 1)) + @schedule.match?(previous).should be_true + end - @schedule.match?(previous).should be_false - end -end + it "should not match if the previous time is after the most recent Saturday" do + now = Time.now -describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do - include ScheduleTesting + # Subtract the number days we've progressed into the week + previous = now - (3600 * 24 * now.wday) - before do - @schedule[:period] = :daily - @schedule[:repeat] = 2 + @schedule.match?(previous).should be_false + end end - it "should fail if the periodmatch is 'number'" do - @schedule[:periodmatch] = :number - proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error) - end + describe Puppet::Type::Schedule, "when matching monthly by number" do + include ScheduleTesting - it "should match if the previous run was further away than the distance divided by the repeat" do - previous = Time.now - (3600 * 13) - @schedule.match?(previous).should be_true - end + before do + @schedule[:period] = :monthly + @schedule[:periodmatch] = :number + end - it "should not match if the previous run was closer than the distance divided by the repeat" do - previous = Time.now - (3600 * 11) - @schedule.match?(previous).should be_false - end -end + it "should match when the previous time is prior to the first day of this month" do + now = Time.now -module OldTesting - def mksched - @stype.create(:name => "testsched") - end + # Subtract the number days we've progressed into the month + previous = now - (3600 * 24 * now.day) + + @schedule.match?(previous).should be_true + end - def test_period_with_repeat - previous = @now + it "should not match when the previous time is after the last day of last month" do + now = Time.now - s = mksched - s[:period] = :hourly + # Subtract the number days we've progressed into the month, minus one + previous = now - (3600 * 24 * (now.day - 1)) - assert_nothing_raised("Was not able to set periodmatch") { - s[:periodmatch] = :number - } - assert_raise(Puppet::Error) { - s[:repeat] = 2 - } - assert_nothing_raised("Was not able to reset periodmatch") { - s[:periodmatch] = :distance - } + @schedule.match?(previous).should be_false + end + end - assert(! s.match?(min("-", 40)), "matched minus 40 minutes") + describe Puppet::Type::Schedule, "when matching with a repeat greater than one" do + include ScheduleTesting - assert_nothing_raised("Was not able to set period") { - s[:repeat] = 2 - } + before do + @schedule[:period] = :daily + @schedule[:repeat] = 2 + end - assert(! s.match?(min("-", 20)), "matched minus 20 minutes with half-hourly") - assert(s.match?(min("-", 40)), "Did not match minus 40 with half-hourly") + it "should fail if the periodmatch is 'number'" do + @schedule[:periodmatch] = :number + proc { @schedule[:repeat] = 2 }.should raise_error(Puppet::Error) + end - assert_nothing_raised("Was not able to set period") { - s[:repeat] = 3 - } + it "should match if the previous run was further away than the distance divided by the repeat" do + previous = Time.now - (3600 * 13) + @schedule.match?(previous).should be_true + end - assert(! s.match?(min("-", 15)), "matched minus 15 minutes with half-hourly") - assert(s.match?(min("-", 25)), "Did not match minus 25 with half-hourly") + it "should not match if the previous run was closer than the distance divided by the repeat" do + previous = Time.now - (3600 * 11) + @schedule.match?(previous).should be_false + end end end