diff options
author | Luke Kanies <luke@madstop.com> | 2008-05-13 22:07:18 -0500 |
---|---|---|
committer | Luke Kanies <luke@madstop.com> | 2008-05-13 22:07:18 -0500 |
commit | 121d2911daac533d47bb5c54b042a847f8f36bd3 (patch) | |
tree | 1080b12a3cdad8c7ad74c39cfc05ed186c4cb77f | |
parent | 8971979d4870170d2720275980a64d18ac7bd6bf (diff) | |
download | facter-121d2911daac533d47bb5c54b042a847f8f36bd3.tar.gz facter-121d2911daac533d47bb5c54b042a847f8f36bd3.tar.xz facter-121d2911daac533d47bb5c54b042a847f8f36bd3.zip |
Adding all of the tests for the Facter::Resolution class.
-rw-r--r-- | lib/facter/resolution.rb | 105 | ||||
-rwxr-xr-x | spec/unit/resolution.rb | 184 |
2 files changed, 217 insertions, 72 deletions
diff --git a/lib/facter/resolution.rb b/lib/facter/resolution.rb index 35a931b..7fc1e24 100644 --- a/lib/facter/resolution.rb +++ b/lib/facter/resolution.rb @@ -18,54 +18,40 @@ class Facter::Resolution # Execute a chunk of code. def self.exec(code, interpreter = "/bin/sh") - if interpreter == "/bin/sh" - binary = code.split(/\s+/).shift - - if have_which - path = nil - if binary !~ /^\// - path = %x{which #{binary} 2>/dev/null}.chomp - if path == "" - # we don't have the binary necessary - return nil - end - else - path = binary - end - - unless FileTest.exists?(path) - # our binary does not exist - return nil - end - end - - out = nil - begin - out = %x{#{code}}.chomp - rescue => detail - $stderr.puts detail - return nil - end - if out == "" - return nil + raise ArgumentError, "non-sh interpreters are not currently supported" unless interpreter == "/bin/sh" + binary = code.split(/\s+/).shift + + if have_which + path = nil + if binary !~ /^\// + path = %x{which #{binary} 2>/dev/null}.chomp + # we don't have the binary necessary + return nil if path == "" else - return out + path = binary end + + return nil unless FileTest.exists?(path) + end + + out = nil + begin + out = %x{#{code}}.chomp + rescue => detail + $stderr.puts detail + return nil + end + if out == "" + return nil else - raise ArgumentError, - "non-sh interpreters are not currently supported" + return out end end # Add a new confine to the resolution mechanism. - def confine(*args) - if args[0].is_a? Hash - args[0].each do |fact, values| - @confines.push Facter::Confine.new(fact,*values) - end - else - fact = args.shift - @confines.push Facter::Confine.new(fact,*args) + def confine(confines) + confines.each do |fact, values| + @confines.push Facter::Confine.new(fact, *values) end end @@ -97,56 +83,31 @@ class Facter::Resolution # Set the name by which this parameter is known in LDAP. The default # is just the fact name. def setldapname(name) - @fact.ldapname = name.to_s + fact.ldapname = name.to_s end # Is this resolution mechanism suitable on the system in question? def suitable? unless defined? @suitable - @suitable = true - if @confines.length == 0 - return true - end - @confines.each { |confine| - unless confine.true? - @suitable = false - end - } + @suitable = ! @confines.detect { |confine| ! confine.true? } end return @suitable end - # Set tags on our parent fact. - def tag(*values) - @fact.tag(*values) - end - def to_s return self.value() end # How we get a value for our resolution mechanism. def value - value = nil - if @code.is_a?(Proc) - value = @code.call() + result = @code.call() else - unless defined? @interpreter - @interpreter = "/bin/sh" - end - if @code.nil? - $stderr.puts "Code for %s is nil" % @name - else - value = Facter::Resolution.exec(@code,@interpreter) - end - end - - if value == "" - value = nil + result = Facter::Resolution.exec(@code,@interpreter) end - return value + return nil if result == "" + return result end end diff --git a/spec/unit/resolution.rb b/spec/unit/resolution.rb index 9cb0712..d4dc7e1 100755 --- a/spec/unit/resolution.rb +++ b/spec/unit/resolution.rb @@ -5,4 +5,188 @@ require File.dirname(__FILE__) + '/../spec_helper' require 'facter/resolution' describe Facter::Resolution do + it "should require a name" do + lambda { Facter::Resolution.new }.should raise_error(ArgumentError) + end + + it "should have a name" do + Facter::Resolution.new("yay").name.should == "yay" + end + + it "should have a method for setting the code" do + Facter::Resolution.new("yay").should respond_to(:setcode) + end + + describe "when setting the code" do + before do + @resolve = Facter::Resolution.new("yay") + end + + it "should default to /bin/sh as the interpreter if a string is provided" do + @resolve.setcode "foo" + @resolve.interpreter.should == "/bin/sh" + end + + it "should set the code to any provided string" do + @resolve.setcode "foo" + @resolve.code.should == "foo" + end + + it "should set the code to any provided block" do + block = lambda { } + @resolve.setcode(&block) + @resolve.code.should equal(block) + end + + it "should prefer the string over a block" do + @resolve.setcode("foo") { } + @resolve.code.should == "foo" + end + + it "should fail if neither a string nor block has been provided" do + lambda { @resolve.setcode }.should raise_error(ArgumentError) + end + end + + it "should be able to return a value" do + Facter::Resolution.new("yay").should respond_to(:value) + end + + describe "when returning the value" do + before do + @resolve = Facter::Resolution.new("yay") + end + + describe "and the code is a string" do + it "should return the result of executing the code with the interpreter" do + @resolve.setcode "/bin/foo" + Facter::Resolution.expects(:exec).with("/bin/foo", "/bin/sh").returns "yup" + + @resolve.value.should == "yup" + end + + it "should return nil if the value is an empty string" do + @resolve.setcode "/bin/foo" + Facter::Resolution.stubs(:exec).returns "" + @resolve.value.should be_nil + end + end + + describe "and the code is a block" do + it "should return the value returned by the block" do + @resolve.setcode { "yayness" } + @resolve.value.should == "yayness" + end + + it "should return nil if the value is an empty string" do + @resolve.setcode { "" } + @resolve.value.should be_nil + end + end + end + + it "should return its value when converted to a string" do + @resolve = Facter::Resolution.new("yay") + @resolve.expects(:value).returns "myval" + @resolve.to_s.should == "myval" + end + + it "should allow the adding of confines" do + Facter::Resolution.new("yay").should respond_to(:confine) + end + + it "should provide a method for returning the number of confines" do + @resolve = Facter::Resolution.new("yay") + @resolve.confine "one" => "foo", "two" => "fee" + @resolve.length.should == 2 + end + + it "should return 0 confines when no confines have been added" do + Facter::Resolution.new("yay").length.should == 0 + end + + it "should have a method for determining if it is suitable" do + Facter::Resolution.new("yay").should respond_to(:suitable?) + end + + describe "when adding confines" do + before do + @resolve = Facter::Resolution.new("yay") + end + + it "should accept a hash of fact names and values" do + lambda { @resolve.confine :one => "two" }.should_not raise_error + end + + it "should create a Confine instance for every argument in the provided hash" do + Facter::Confine.expects(:new).with("one", "foo") + Facter::Confine.expects(:new).with("two", "fee") + + @resolve.confine "one" => "foo", "two" => "fee" + end + + end + + describe "when determining suitability" do + before do + @resolve = Facter::Resolution.new("yay") + end + + it "should always be suitable if no confines have been added" do + @resolve.should be_suitable + end + + it "should be unsuitable if any provided confines return false" do + confine1 = mock 'confine1', :true? => true + confine2 = mock 'confine2', :true? => false + Facter::Confine.expects(:new).times(2).returns(confine1).then.returns(confine2) + @resolve.confine :one => :two, :three => :four + + @resolve.should_not be_suitable + end + + it "should be suitable if all provided confines return true" do + confine1 = mock 'confine1', :true? => true + confine2 = mock 'confine2', :true? => true + Facter::Confine.expects(:new).times(2).returns(confine1).then.returns(confine2) + @resolve.confine :one => :two, :three => :four + + @resolve.should be_suitable + end + end + + it "should have a method for setting its ldap name" do + Facter::Resolution.new("yay").should respond_to(:setldapname) + end + + it "should set the ldap name on the associated fact" do + @resolve = Facter::Resolution.new("yay") + fact = mock 'fact' + @resolve.stubs(:fact).returns fact + + fact.expects(:ldapname=).with "ldapness" + + @resolve.setldapname "ldapness" + end + + it "should always convert the ldap name to a string" do + @resolve = Facter::Resolution.new("yay") + fact = mock 'fact' + @resolve.stubs(:fact).returns fact + + fact.expects(:ldapname=).with "ldapness" + + @resolve.setldapname :ldapness + end + + it "should have a class method for executing code" do + Facter::Resolution.should respond_to(:exec) + end + + # It's not possible, AFAICT, to mock %x{}, so I can't really test this bit. + describe "when executing code" do + it "should fail if any interpreter other than /bin/sh is requested" do + lambda { Facter::Resolution.exec("/something", "/bin/perl") }.should raise_error(ArgumentError) + end + end end |