diff options
-rw-r--r-- | lib/puppet/util/feature.rb | 36 | ||||
-rwxr-xr-x | spec/integration/util/feature.rb | 54 | ||||
-rwxr-xr-x | spec/unit/util/feature.rb | 70 | ||||
-rwxr-xr-x | test/util/features.rb | 95 |
4 files changed, 145 insertions, 110 deletions
diff --git a/lib/puppet/util/feature.rb b/lib/puppet/util/feature.rb index 94ee3be8b..102bca778 100644 --- a/lib/puppet/util/feature.rb +++ b/lib/puppet/util/feature.rb @@ -63,23 +63,29 @@ class Puppet::Util::Feature # someone asks for the feature, so we don't unnecessarily load # files. def test(name, options) - result = true - if ary = options[:libs] - ary = [ary] unless ary.is_a?(Array) + return true unless ary = options[:libs] + ary = [ary] unless ary.is_a?(Array) - ary.each do |lib| - unless lib.is_a?(String) - raise ArgumentError, "Libraries must be passed as strings not %s" % lib.class - end + ary.each do |lib| + load_library(lib) + end - begin - require lib - rescue Exception - Puppet.debug "Failed to load library '%s' for feature '%s'" % [lib, name] - result = false - end - end + # We loaded all of the required libraries + return true + end + + private + + def load_library(lib) + unless lib.is_a?(String) + raise ArgumentError, "Libraries must be passed as strings not %s" % lib.class + end + + begin + require lib + rescue Exception + Puppet.debug "Failed to load library '%s' for feature '%s'" % [lib, name] + result = false end - result end end diff --git a/spec/integration/util/feature.rb b/spec/integration/util/feature.rb new file mode 100755 index 000000000..f1ddd5d43 --- /dev/null +++ b/spec/integration/util/feature.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +require 'puppet/util/feature' +require 'puppet_spec/files' + +describe Puppet::Util::Feature do + include PuppetSpec::Files + + it "should be able to load features from disk" do + libdir = tmpfile("feature_lib") + Dir.mkdir(libdir) + + $: << libdir + + $features = Puppet::Util::Feature.new("feature_lib") + + Dir.mkdir(File.join(libdir, "feature_lib")) + + File.open(File.join(libdir, "feature_lib", "able_to_load.rb"), "w") do |f| + f.puts "$features.add(:able_to_load) { true }" + end + + $features.should be_able_to_load + end + + + def test_dynamic_loading + $features = @features + cleanup { $features = nil } + # Now create a feature and make sure it loads. + FileUtils.mkdir_p(@path) + nope = File.join(@path, "nope.rb") + File.open(nope, "w") { |f| + f.puts "$features.add(:nope, :libs => %w{nosuchlib})" + } + assert_nothing_raised("Failed to autoload features") do + assert(! @features.nope?, "'nope' returned true") + end + + # First make sure "yep?" returns false + assert_nothing_raised("Missing feature threw an exception") do + assert(! @features.notyep?, "'notyep' returned true before definition") + end + + yep = File.join(@path, "yep.rb") + File.open(yep, "w") { |f| + f.puts "$features.add(:yep, :libs => %w{puppet})" + } + + assert(@features.yep?, "false 'yep' is apparently cached or feature could not be loaded") + end +end diff --git a/spec/unit/util/feature.rb b/spec/unit/util/feature.rb new file mode 100755 index 000000000..cf7d06614 --- /dev/null +++ b/spec/unit/util/feature.rb @@ -0,0 +1,70 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") } + +require 'puppet/util/feature' + +describe Puppet::Util::Feature do + before do + @features = Puppet::Util::Feature.new("features") + @features.stubs(:warn) + end + + it "should consider undefined features to be absent" do + @features.should_not be_defined_feature + end + + it "should be able to add new features" do + @features.add(:myfeature) {} + @features.should respond_to(:myfeature?) + end + + it "should call associated code when loading a feature" do + $loaded_feature = false + @features.add(:myfeature) { $loaded_feature = true} + $loaded_feature.should be_true + end + + it "should consider a feature absent when the feature load fails" do + @features.add(:failer) { raise "foo" } + @features.should_not be_failer + end + + it "should consider a feature to be absent when the feature load returns false" do + @features.add(:failer) { false } + @features.should_not be_failer + end + + it "should consider a feature to be present when the feature load returns true" do + @features.add(:available) { true } + @features.should be_available + end + + it "should cache the results of a feature load" do + $loaded_feature = 0 + @features.add(:myfeature) { $loaded_feature += 1 } + @features.myfeature? + @features.myfeature? + $loaded_feature.should == 1 + end + + it "should support features with libraries" do + lambda { @features.add(:puppet, :libs => %w{puppet}) }.should_not raise_error + end + + it "should consider a feature to be present if all of its libraries are present" do + @features.add(:myfeature, :libs => %w{foo bar}) + @features.expects(:require).with("foo") + @features.expects(:require).with("bar") + + @features.should be_myfeature + end + + it "should consider a feature to be absent if any of its libraries are absent" do + @features.add(:myfeature, :libs => %w{foo bar}) + @features.expects(:require).with("foo") + @features.expects(:require).with("bar").raises(LoadError) + + @features.should_not be_myfeature + end +end diff --git a/test/util/features.rb b/test/util/features.rb deleted file mode 100755 index 8788599ce..000000000 --- a/test/util/features.rb +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Luke Kanies on 2006-11-07. -# Copyright (c) 2006. All rights reserved. - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'puppettest' -require 'puppet/util/feature' - -class TestFeatures < Test::Unit::TestCase - include PuppetTest - - def setup - super - @libdir = tempfile() - Puppet[:libdir] = @libdir - @path = File.join(@libdir, "features") - @features = Puppet::Util::Feature.new("features") - end - - def test_new - redirect - assert_nothing_raised do - @features.add(:failer) do - raise ArgumentError, "nopes" - end - end - - assert(@features.respond_to?(:failer?), "Feature method did not get added") - assert_nothing_raised("failure propagated outside of feature") do - assert(! @features.failer?, "failure was considered true") - end - - # Now make one that succeeds - $succeeds = nil - assert_nothing_raised("Failed to add normal feature") do - @features.add(:succeeds) do - $succeeds = true - end - end - assert($succeeds, "Block was not called on initialization") - - assert(@features.respond_to?(:succeeds?), "Did not add succeeding feature") - assert_nothing_raised("Failed to call succeeds") { assert(@features.succeeds?, "Feature was not true") } - end - - def test_libs - assert_nothing_raised do - @features.add(:puppet, :libs => %w{puppet}) - end - - assert(@features.puppet?) - - assert_nothing_raised do - @features.add(:missing, :libs => %w{puppet no/such/library/okay}) - end - - assert(! @features.missing?, "Missing lib was considered true") - end - - def test_dynamic_loading - # Make sure it defaults to false - assert_nothing_raised("Undefined features throw an exception") do - assert(! @features.nosuchfeature?, "missing feature returned true") - end - - $features = @features - cleanup { $features = nil } - # Now create a feature and make sure it loads. - FileUtils.mkdir_p(@path) - nope = File.join(@path, "nope.rb") - File.open(nope, "w") { |f| - f.puts "$features.add(:nope, :libs => %w{nosuchlib})" - } - assert_nothing_raised("Failed to autoload features") do - assert(! @features.nope?, "'nope' returned true") - end - - # First make sure "yep?" returns false - assert_nothing_raised("Missing feature threw an exception") do - assert(! @features.yep?, "'yep' returned true before definition") - end - - yep = File.join(@path, "yep.rb") - File.open(yep, "w") { |f| - f.puts "$features.add(:yep, :libs => %w{puppet})" - } - - # Now make sure the value is not cached or anything. - assert_nothing_raised("Failed to autoload features") do - assert(@features.yep?, "'yep' returned false") - end - end -end |