summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/util/feature.rb36
-rwxr-xr-xspec/integration/util/feature.rb54
-rwxr-xr-xspec/unit/util/feature.rb70
-rwxr-xr-xtest/util/features.rb95
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