Reviewed-by: Max Martin <m...@puppetlabs.com>
Signed-off-by: Paul Berry <p...@puppetlabs.com>
---
 lib/puppet/util.rb                    |    5 ++++
 lib/puppet/util/execution_stub.rb     |   26 ++++++++++++++++++++++++
 spec/spec_helper.rb                   |    1 +
 spec/unit/util/execution_stub_spec.rb |   35 +++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 0 deletions(-)
 create mode 100644 lib/puppet/util/execution_stub.rb
 create mode 100644 spec/unit/util/execution_stub_spec.rb

diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index 850d147..d06f448 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -4,6 +4,7 @@ require 'puppet/util/monkey_patches'
 require 'sync'
 require 'puppet/external/lock'
 require 'monitor'
+require 'puppet/util/execution_stub'
 
 module Puppet
   # A command failed to execute.
@@ -264,6 +265,10 @@ module Util
     arguments[:uid] = Puppet::Util::SUIDManager.convert_xid(:uid, 
arguments[:uid]) if arguments[:uid]
     arguments[:gid] = Puppet::Util::SUIDManager.convert_xid(:gid, 
arguments[:gid]) if arguments[:gid]
 
+    if execution_stub = Puppet::Util::ExecutionStub.current_value
+      return execution_stub.call(command, arguments)
+    end
+
     @@os ||= Facter.value(:operatingsystem)
     output = nil
     child_pid, child_status = nil
diff --git a/lib/puppet/util/execution_stub.rb 
b/lib/puppet/util/execution_stub.rb
new file mode 100644
index 0000000..af74e0f
--- /dev/null
+++ b/lib/puppet/util/execution_stub.rb
@@ -0,0 +1,26 @@
+module Puppet::Util
+  class ExecutionStub
+    class << self
+      # Set a stub block that Puppet::Util.execute() should invoke instead
+      # of actually executing commands on the target machine.  Intended
+      # for spec testing.
+      #
+      # The arguments passed to the block are |command, options|, where
+      # command is an array of strings and options is an options hash.
+      def set(&block)
+        @value = block
+      end
+
+      # Uninstall any execution stub, so that calls to
+      # Puppet::Util.execute() behave normally again.
+      def reset
+        @value = nil
+      end
+
+      # Retrieve the current execution stub, or nil if there is no stub.
+      def current_value
+        @value
+      end
+    end
+  end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a374fb0..ae4edb2 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -34,6 +34,7 @@ RSpec.configure do |config|
     Puppet.settings.clear
     Puppet::Node::Environment.clear
     Puppet::Util::Storage.clear
+    Puppet::Util::ExecutionStub.reset
 
     if defined?($tmpfiles)
       $tmpfiles.each do |file|
diff --git a/spec/unit/util/execution_stub_spec.rb 
b/spec/unit/util/execution_stub_spec.rb
new file mode 100644
index 0000000..14cf9c6
--- /dev/null
+++ b/spec/unit/util/execution_stub_spec.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+describe Puppet::Util::ExecutionStub do
+  it "should use the provided stub code when 'set' is called" do
+    Puppet::Util::ExecutionStub.set do |command, options|
+      command.should == ['/bin/foo', 'bar']
+      "stub output"
+    end
+    Puppet::Util::ExecutionStub.current_value.should_not == nil
+    Puppet::Util.execute(['/bin/foo', 'bar']).should == "stub output"
+  end
+
+  it "should automatically restore normal execution at the conclusion of each 
spec test" do
+    # Note: this test relies on the previous test creating a stub.
+    Puppet::Util::ExecutionStub.current_value.should == nil
+  end
+
+  it "should restore normal execution after 'reset' is called" do
+    true_command = Puppet::Util.which('true') # Note: "true" exists at 
different paths in different OSes
+    stub_call_count = 0
+    Puppet::Util::ExecutionStub.set do |command, options|
+      command.should == [true_command]
+      stub_call_count += 1
+      'stub called'
+    end
+    Puppet::Util.execute([true_command]).should == 'stub called'
+    stub_call_count.should == 1
+    Puppet::Util::ExecutionStub.reset
+    Puppet::Util::ExecutionStub.current_value.should == nil
+    Puppet::Util.execute([true_command]).should == ''
+    stub_call_count.should == 1
+  end
+end
-- 
1.7.2

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to puppet-dev@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to