diff --git a/lib/puppet/util/feature.rb b/lib/puppet/util/feature.rb index 102bca778..add1b2691 100644 --- a/lib/puppet/util/feature.rb +++ b/lib/puppet/util/feature.rb @@ -1,91 +1,92 @@ # Created by Luke Kanies on 2006-11-07. # Copyright (c) 2006. All rights reserved. class Puppet::Util::Feature attr_reader :path # Create a new feature test. You have to pass the feature name, # and it must be unique. You can either provide a block that # will get executed immediately to determine if the feature # is present, or you can pass an option to determine it. # Currently, the only supported option is 'libs' (must be # passed as a symbol), which will make sure that each lib loads # successfully. def add(name, options = {}) method = name.to_s + "?" if self.class.respond_to?(method) raise ArgumentError, "Feature %s is already defined" % name end if block_given? begin result = yield rescue => detail warn "Failed to load feature test for %s: %s" % [name, detail] result = false end @results[name] = result end meta_def(method) do unless @results.include?(name) @results[name] = test(name, options) end @results[name] end end # Create a new feature collection. def initialize(path) @path = path @results = {} @loader = Puppet::Util::Autoload.new(self, @path) end def load @loader.loadall end def method_missing(method, *args) return super unless method.to_s =~ /\?$/ feature = method.to_s.sub(/\?$/, '') @loader.load(feature) if respond_to?(method) return self.send(method) else return false end end # Actually test whether the feature is present. We only want to test when # someone asks for the feature, so we don't unnecessarily load # files. def test(name, options) return true unless ary = options[:libs] ary = [ary] unless ary.is_a?(Array) ary.each do |lib| - load_library(lib) + return false unless load_library(lib, name) end # We loaded all of the required libraries return true end private - def load_library(lib) + def load_library(lib, name) 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 + return false end + return true end end diff --git a/spec/unit/util/feature.rb b/spec/unit/util/feature.rb index cf7d06614..576e19bc8 100755 --- a/spec/unit/util/feature.rb +++ b/spec/unit/util/feature.rb @@ -1,70 +1,72 @@ #!/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 + it "should log and 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.expects(:require).with("foo").raises(LoadError) + @features.stubs(:require).with("bar") + + Puppet.expects(:debug) @features.should_not be_myfeature end end