Permalink
Browse files

Utilities updates

Allows the helper methods that perform system calls to be stubbed for
all specs in the spec_helper.
  • Loading branch information...
Brian D. Burns
Brian D. Burns committed Mar 20, 2013
1 parent e1a7bfd commit 4793a91a0927851eceeff04b2fb7e5230116ea10
Showing with 140 additions and 116 deletions.
  1. +112 −103 lib/backup/utilities.rb
  2. +1 −0 spec/pipeline_spec.rb
  3. +5 −1 spec/spec_helper.rb
  4. +22 −12 spec/utilities_spec.rb
View
@@ -11,7 +11,107 @@ module Utilities
rsync
}
- module Helpers
+ module DSL
+ class << self
+ ##
+ # Allow users to set the path for all utilities in the .configure block.
+ #
+ # Utility names with dashes ('redis-cli') will be set using method calls
+ # with an underscore ('redis_cli').
+ NAMES.each do |name|
+ define_method name.gsub('-', '_'), lambda {|val|
+ path = File.expand_path(val)
+ unless File.executable?(path)
+ raise Errors::Utilities::NotFoundError, <<-EOS
+ The path given for '#{ name }' was not found or not executable.
+ Path was: #{ path }
+ EOS
+ end
+ UTILITY[name] = path
+ }
+ end
+
+ ##
+ # Allow users to set the +tar+ distribution if needed. (:gnu or :bsd)
+ def tar_dist(val)
+ Utilities.tar_dist(val)
+ end
+ end
+ end
+
+ class << self
+ ##
+ # Configure the path to system utilities used by Backup.
+ #
+ # Backup will attempt to locate any required system utilities using a
+ # +which+ command call. If a utility can not be found, or you need to
+ # specify an alternate path for a utility, you may do so in your
+ # +config.rb+ file using this method.
+ #
+ # Backup supports both GNU and BSD utilities.
+ # While Backup uses these utilities in a manner compatible with either
+ # version, the +tar+ utility requires some special handling with respect
+ # to +Archive+s. Backup will attempt to detect if the +tar+ command
+ # found (or set here) is GNU or BSD. If for some reason this fails,
+ # this may be set using the +tar_dist+ command shown below.
+ #
+ # Backup::Utilities.configure do
+ # # General Utilites
+ # tar '/path/to/tar'
+ # tar_dist :gnu # or :bsd
+ # cat '/path/to/cat'
+ # split '/path/to/split'
+ # find '/path/to/find'
+ # xargs '/path/to/xargs'
+ #
+ # # Compressors
+ # gzip '/path/to/gzip'
+ # bzip2 '/path/to/bzip2'
+ # lzma '/path/to/lzma' # deprecated. use a Custom Compressor
+ # pbzip2 '/path/to/pbzip2' # deprecated. use a Custom Compressor
+ #
+ # # Database Utilities
+ # mongo '/path/to/mongo'
+ # mongodump '/path/to/mongodump'
+ # mysqldump '/path/to/mysqldump'
+ # pg_dump '/path/to/pg_dump'
+ # redis_cli '/path/to/redis-cli'
+ # riak_admin '/path/to/riak-admin'
+ #
+ # # Encryptors
+ # gpg '/path/to/gpg'
+ # openssl '/path/to/openssl'
+ #
+ # # Syncer and Storage
+ # rsync '/path/to/rsync'
+ # end
+ #
+ # These paths may be set using absolute paths, or relative to the
+ # working directory when Backup is run.
+ #
+ # Note that many of Backup's components currently have their own
+ # configuration settings for utility paths. For instance, when configuring
+ # a +MySQL+ database backup, +mysqldump_utility+ may be used:
+ #
+ # database MySQL do |db|
+ # db.mysqldump_utility = '/path/to/mysqldump'
+ # end
+ #
+ # Use of these configuration settings will override the path set here.
+ # (The use of these may be deprecated in the future)
+ def configure(&block)
+ DSL.instance_eval(&block)
+ end
+
+ def tar_dist(val)
+ @gnu_tar = val == :gnu
+ end
+
+ def gnu_tar?
+ return @gnu_tar unless @gnu_tar.nil?
+ @gnu_tar = !!run("#{ utility(:tar) } --version").match(/GNU/)
+ end
+
private
##
@@ -100,112 +200,21 @@ def run(command)
end
end
- def gnu_tar?
- Utilities.gnu_tar?
- end
- end # Helpers
-
- class << self
- include Helpers
-
- ##
- # Configure the path to system utilities used by Backup.
- #
- # Backup will attempt to locate any required system utilities using a
- # +which+ command call. If a utility can not be found, or you need to
- # specify an alternate path for a utility, you may do so in your
- # +config.rb+ file using this method.
- #
- # Backup supports both GNU and BSD utilities.
- # While Backup uses these utilities in a manner compatible with either
- # version, the +tar+ utility requires some special handling with respect
- # to +Archive+s. Backup will attempt to detect if the +tar+ command
- # found (or set here) is GNU or BSD. If for some reason this fails,
- # this may be set using the +tar_dist+ command shown below.
- #
- # Backup::Utilities.configure do
- # # General Utilites
- # tar '/path/to/tar'
- # tar_dist :gnu # or :bsd
- # cat '/path/to/cat'
- # split '/path/to/split'
- # find '/path/to/find'
- # xargs '/path/to/xargs'
- #
- # # Compressors
- # gzip '/path/to/gzip'
- # bzip2 '/path/to/bzip2'
- # lzma '/path/to/lzma' # deprecated. use a Custom Compressor
- # pbzip2 '/path/to/pbzip2' # deprecated. use a Custom Compressor
- #
- # # Database Utilities
- # mongo '/path/to/mongo'
- # mongodump '/path/to/mongodump'
- # mysqldump '/path/to/mysqldump'
- # pg_dump '/path/to/pg_dump'
- # redis_cli '/path/to/redis-cli'
- # riak_admin '/path/to/riak-admin'
- #
- # # Encryptors
- # gpg '/path/to/gpg'
- # openssl '/path/to/openssl'
- #
- # # Syncer and Storage
- # rsync '/path/to/rsync'
- # end
- #
- # These paths may be set using absolute paths, or relative to the
- # working directory when Backup is run.
- #
- # Note that many of Backup's components currently have their own
- # configuration settings for utility paths. For instance, when configuring
- # a +MySQL+ database backup, +mysqldump_utility+ may be used:
- #
- # database MySQL do |db|
- # db.mysqldump_utility = '/path/to/mysqldump'
- # end
- #
- # Use of these configuration settings will override the path set here.
- # (The use of these may be deprecated in the future)
- def configure(&block)
- instance_eval(&block)
- end
-
- def gnu_tar?
- return @gnu_tar unless @gnu_tar.nil?
- @gnu_tar = !!run("#{ utility(:tar) } --version").match(/GNU/)
- end
-
- private
-
- ##
- # Allow users to set the path for all utilities in the .configure block.
- #
- # Utility names with dashes ('redis-cli') will be set using method calls
- # with an underscore ('redis_cli').
- NAMES.each do |name|
- define_method name.gsub('-', '_'), lambda {|val|
- path = File.expand_path(val)
- unless File.executable?(path)
- raise Errors::Utilities::NotFoundError, <<-EOS
- The path given for '#{ name }' was not found or not executable.
- Path was: #{ path }
- EOS
- end
- UTILITY[name] = path
- }
- end
-
- ##
- # Allow users to set the +tar+ distribution if needed. (:gnu or :bsd)
- def tar_dist(val)
- @gnu_tar = val == :gnu
- end
-
def reset!
UTILITY.clear
@gnu_tar = nil
end
end
+
+ # Allows these utility methods to be included in other classes,
+ # while allowing them to be stubbed in spec_helper for all specs.
+ module Helpers
+ [:utility, :command_name, :run].each do |name|
+ define_method name, lambda {|arg| Utilities.send(name, arg) }
+ private name
+ end
+ private
+ def gnu_tar?; Utilities.gnu_tar?; end
+ end
end
end
View
@@ -45,6 +45,7 @@
let(:stderr) { mock }
before do
+ Backup::Pipeline.any_instance.unstub(:run)
pipeline.expects(:pipeline).returns('foo')
# stub Utilities::Helpers#command_name so it simply returns what it's passed
pipeline.class.send(:define_method, :command_name, lambda {|arg| arg } )
View
@@ -51,7 +51,11 @@ def capture_io
# ::FileUtils will always be either SandboxFileUtils or FileUtils::NoWrite.
SandboxFileUtils.deactivate!(:noop)
- Open4.stubs(:popen4).raises('Unexpected call to Open4::popen4()')
+ # prevent system calls
+ Backup::Utilities.stubs(:gnu_tar?).returns(true)
+ Backup::Utilities.stubs(:utility)
+ Backup::Utilities.stubs(:run)
+ Backup::Pipeline.any_instance.stubs(:run)
Backup::Utilities.send(:reset!)
Backup::Config.send(:reset!)
View
@@ -8,14 +8,11 @@
# Note: spec_helper resets Utilities before each example
- it 'includes Utilities::Helpers' do
- utilities.instance_eval('class << self; self; end').
- include?(Backup::Utilities::Helpers).should be_true
- end
-
describe '.configure' do
before do
File.stubs(:executable?).returns(true)
+ utilities.unstub(:gnu_tar?)
+ utilities.unstub(:utility)
utilities.configure do
# General Utilites
@@ -91,6 +88,10 @@
end # describe '.configure'
describe '.gnu_tar?' do
+ before do
+ utilities.unstub(:gnu_tar?)
+ end
+
it 'determines when tar is GNU tar' do
utilities.expects(:utility).with(:tar).returns('tar')
utilities.expects(:run).with('tar --version').returns(
@@ -126,24 +127,29 @@
describe Backup::Utilities::Helpers do
let(:helpers) { Module.new.extend(Backup::Utilities::Helpers) }
+ let(:utilities) { Backup::Utilities }
describe '#utility' do
+ before do
+ utilities.unstub(:utility)
+ end
+
context 'when a system path for the utility is available' do
it 'should return the system path with newline removed' do
- helpers.expects(:`).with("which 'foo' 2>/dev/null").returns("system_path\n")
+ utilities.expects(:`).with("which 'foo' 2>/dev/null").returns("system_path\n")
helpers.send(:utility, :foo).should == 'system_path'
end
it 'should cache the returned path' do
- helpers.expects(:`).once.with("which 'cache_me' 2>/dev/null").
+ utilities.expects(:`).once.with("which 'cache_me' 2>/dev/null").
returns("cached_path\n")
helpers.send(:utility, :cache_me).should == 'cached_path'
helpers.send(:utility, :cache_me).should == 'cached_path'
end
it 'should cache the value for all extended objects' do
- helpers.expects(:`).once.with("which 'once_only' 2>/dev/null").
+ utilities.expects(:`).once.with("which 'once_only' 2>/dev/null").
returns("cached_path\n")
helpers.send(:utility, :once_only).should == 'cached_path'
@@ -154,7 +160,7 @@
context 'when a system path for the utility is not available' do
it 'should raise an error' do
- helpers.expects(:`).with("which 'unknown' 2>/dev/null").returns("\n")
+ utilities.expects(:`).with("which 'unknown' 2>/dev/null").returns("\n")
expect do
helpers.send(:utility, :unknown)
@@ -164,7 +170,7 @@
end
it 'should not cache any value for the utility' do
- helpers.expects(:`).with("which 'not_cached' 2>/dev/null").twice.returns("\n")
+ utilities.expects(:`).with("which 'not_cached' 2>/dev/null").twice.returns("\n")
expect do
helpers.send(:utility, :not_cached)
@@ -181,7 +187,7 @@
end
it 'should raise an error if name is nil' do
- helpers.expects(:`).never
+ utilities.expects(:`).never
expect do
helpers.send(:utility, nil)
end.to raise_error(
@@ -191,7 +197,7 @@
end
it 'should raise an error if name is empty' do
- helpers.expects(:`).never
+ utilities.expects(:`).never
expect do
helpers.send(:utility, ' ')
end.to raise_error(
@@ -245,6 +251,10 @@
let(:process_status) { stub(:success? => process_success) }
let(:command) { '/path/to/cmd_name arg1 arg2' }
+ before do
+ utilities.unstub(:run)
+ end
+
context 'when the command is successful' do
let(:process_success) { true }

0 comments on commit 4793a91

Please sign in to comment.