summaryrefslogtreecommitdiffstats
path: root/spec/unit
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-02-13 18:24:34 -0600
committerLuke Kanies <luke@madstop.com>2009-02-13 18:24:34 -0600
commit3fbec120768d84d208b14f574dfe916e25cfdbef (patch)
tree865d59f4ea9cf3782db46ce1ae7fd54b95945035 /spec/unit
parenta2270b4a4f093c6c4f171dcf0c0e05fe101dd979 (diff)
parent2561c8e252dcf66890513458750bb1329a03beec (diff)
downloadpuppet-3fbec120768d84d208b14f574dfe916e25cfdbef.tar.gz
puppet-3fbec120768d84d208b14f574dfe916e25cfdbef.tar.xz
puppet-3fbec120768d84d208b14f574dfe916e25cfdbef.zip
Merge branch '0.24.x'
Conflicts: lib/puppet/indirector/facts/facter.rb lib/puppet/provider/augeas/augeas.rb lib/puppet/util/filetype.rb spec/unit/indirector/facts/facter.rb spec/unit/provider/augeas/augeas.rb test/util/filetype.rb
Diffstat (limited to 'spec/unit')
-rwxr-xr-xspec/unit/indirector/facts/facter.rb38
-rwxr-xr-xspec/unit/network/xmlrpc/client.rb172
-rw-r--r--spec/unit/parser/functions/regsubst.rb88
-rw-r--r--spec/unit/parser/functions/sprintf.rb42
-rw-r--r--spec/unit/provider/augeas/augeas.rb30
-rwxr-xr-xspec/unit/provider/parsedfile.rb36
-rwxr-xr-xspec/unit/util/autoload.rb39
-rw-r--r--spec/unit/util/filetype.rb110
8 files changed, 529 insertions, 26 deletions
diff --git a/spec/unit/indirector/facts/facter.rb b/spec/unit/indirector/facts/facter.rb
index c0b9dce36..ea68f63d6 100755
--- a/spec/unit/indirector/facts/facter.rb
+++ b/spec/unit/indirector/facts/facter.rb
@@ -93,15 +93,6 @@ describe Puppet::Node::Facts::Facter do
end
end
- it "should load each directory in the Fact path when loading fact plugins" do
- Puppet.settings.expects(:value).with(:factpath).returns("one%stwo" % File::PATH_SEPARATOR)
-
- Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("one")
- Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("two")
-
- Puppet::Node::Facts::Facter.load_fact_plugins
- end
-
it "should skip files when asked to load a directory" do
FileTest.expects(:directory?).with("myfile").returns false
@@ -119,4 +110,33 @@ describe Puppet::Node::Facts::Facter do
Puppet::Node::Facts::Facter.load_facts_in_dir("mydir")
end
+
+ describe Puppet::Node::Facts::Facter, "when loading fact plugins from disk" do
+ it "should load each directory in the Fact path" do
+ Puppet.settings.stubs(:value).returns "foo"
+ Puppet.settings.expects(:value).with(:factpath).returns("one%stwo" % File::PATH_SEPARATOR)
+
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("one")
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("two")
+
+ Puppet::Node::Facts::Facter.load_fact_plugins
+ end
+
+ it "should load all facts from the modules" do
+ Puppet.settings.stubs(:value).returns "foo"
+ Puppet::Node::Facts::Facter.stubs(:load_facts_in_dir)
+
+ Puppet.settings.expects(:value).with(:modulepath).returns("one%stwo" % File::PATH_SEPARATOR)
+
+ Dir.expects(:glob).with("one/*/plugins/facter").returns %w{oneA oneB}
+ Dir.expects(:glob).with("two/*/plugins/facter").returns %w{twoA twoB}
+
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("oneA")
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("oneB")
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("twoA")
+ Puppet::Node::Facts::Facter.expects(:load_facts_in_dir).with("twoB")
+
+ Puppet::Node::Facts::Facter.load_fact_plugins
+ end
+ end
end
diff --git a/spec/unit/network/xmlrpc/client.rb b/spec/unit/network/xmlrpc/client.rb
index a0a2e77fb..36e59429c 100755
--- a/spec/unit/network/xmlrpc/client.rb
+++ b/spec/unit/network/xmlrpc/client.rb
@@ -2,12 +2,170 @@
Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
-describe Puppet::Network do
- it "should raise an XMLRPCClientError if a generated class raises a Timeout::Error" do
- http = mock 'http'
- Puppet::Network::HttpPool.stubs(:http_instance).returns http
- file = Puppet::Network::Client.file.new({:Server => "foo.com"})
- http.stubs(:post2).raises Timeout::Error
- lambda { file.retrieve }.should raise_error(Puppet::Network::XMLRPCClientError)
+describe Puppet::Network::XMLRPCClient do
+ describe "when performing the rpc call" do
+ before do
+ @client = Puppet::Network::Client.report.xmlrpc_client.new
+ @client.stubs(:call).returns "foo"
+
+ end
+
+ it "should call the specified namespace and method, with the specified arguments" do
+ @client.expects(:call).with("puppetreports.report", "eh").returns "foo"
+ @client.report("eh")
+ end
+
+ it "should return the results from the call" do
+ @client.expects(:call).returns "foo"
+ @client.report("eh").should == "foo"
+ end
+
+ it "should always close the http connection if it is still open after the call" do
+ http = mock 'http'
+ @client.stubs(:http).returns http
+
+ http.expects(:started?).returns true
+ http.expects(:finish)
+
+ @client.report("eh").should == "foo"
+ end
+
+ it "should always close the http connection if it is still open after a call that raises an exception" do
+ http = mock 'http'
+ @client.stubs(:http).returns http
+
+ @client.expects(:call).raises RuntimeError
+
+ http.expects(:started?).returns true
+ http.expects(:finish)
+
+ lambda { @client.report("eh") }.should raise_error
+ end
+
+ describe "when returning the http instance" do
+ it "should use the http pool to create the instance" do
+ @client.instance_variable_set("@http", nil)
+ @client.expects(:host).returns "myhost"
+ @client.expects(:port).returns "myport"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myhost", "myport", true).returns "http"
+
+ @client.http.should == "http"
+ end
+
+ it "should reuse existing instances" do
+ @client.http.should equal(@client.http)
+ end
+ end
+
+ describe "when recycling the connection" do
+ it "should close the existing instance if it's open" do
+ http = mock 'http'
+ @client.stubs(:http).returns http
+
+ http.expects(:started?).returns true
+ http.expects(:finish)
+
+ @client.recycle_connection
+ end
+
+ it "should force creation of a new instance" do
+ Puppet::Network::HttpPool.expects(:http_instance).returns "second_http"
+
+ @client.recycle_connection
+
+ @client.http.should == "second_http"
+ end
+ end
+
+ describe "and an exception is raised" do
+ it "should raise XMLRPCClientError if XMLRPC::FaultException is raised" do
+ error = XMLRPC::FaultException.new("foo", "bar")
+
+ @client.expects(:call).raises(error)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should raise XMLRPCClientError if Errno::ECONNREFUSED is raised" do
+ @client.expects(:call).raises(Errno::ECONNREFUSED)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should log and raise XMLRPCClientError if Timeout::Error is raised" do
+ Puppet.expects(:err)
+ @client.expects(:call).raises(Timeout::Error)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should log and raise XMLRPCClientError if SocketError is raised" do
+ Puppet.expects(:err)
+ @client.expects(:call).raises(SocketError)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should log, recycle the connection, and retry if Errno::EPIPE is raised" do
+ @client.expects(:call).times(2).raises(Errno::EPIPE).then.returns "eh"
+
+ Puppet.expects(:warning)
+ @client.expects(:recycle_connection)
+
+ @client.report("eh")
+ end
+
+ it "should log, recycle the connection, and retry if EOFError is raised" do
+ @client.expects(:call).times(2).raises(EOFError).then.returns "eh"
+
+ Puppet.expects(:warning)
+ @client.expects(:recycle_connection)
+
+ @client.report("eh")
+ end
+
+ it "should log and retry if an exception containing 'Wrong size' is raised" do
+ error = RuntimeError.new("Wrong size. Was 15, should be 30")
+ @client.expects(:call).times(2).raises(error).then.returns "eh"
+
+ Puppet.expects(:warning)
+
+ @client.report("eh")
+ end
+
+ it "should raise XMLRPCClientError if OpenSSL::SSL::SSLError is raised" do
+ @client.expects(:call).raises(OpenSSL::SSL::SSLError)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should log and raise XMLRPCClientError if OpenSSL::SSL::SSLError is raised with certificate issues" do
+ error = OpenSSL::SSL::SSLError.new("hostname was not match")
+ @client.expects(:call).raises(error)
+
+ Puppet.expects(:warning)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+
+ it "should log, recycle the connection, and retry if OpenSSL::SSL::SSLError is raised containing 'bad write retry'" do
+ error = OpenSSL::SSL::SSLError.new("bad write retry")
+ @client.expects(:call).times(2).raises(error).then.returns "eh"
+
+ @client.expects(:recycle_connection)
+
+ Puppet.expects(:warning)
+
+ @client.report("eh")
+ end
+
+ it "should log and raise XMLRPCClientError if any other exception is raised" do
+ @client.expects(:call).raises(RuntimeError)
+
+ Puppet.expects(:err)
+
+ lambda { @client.report("eh") }.should raise_error(Puppet::Network::XMLRPCClientError)
+ end
+ end
end
end
diff --git a/spec/unit/parser/functions/regsubst.rb b/spec/unit/parser/functions/regsubst.rb
new file mode 100644
index 000000000..18f49f7d4
--- /dev/null
+++ b/spec/unit/parser/functions/regsubst.rb
@@ -0,0 +1,88 @@
+#! /usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe "the regsubst function" do
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("regsubst").should == "function_regsubst"
+ end
+
+ it "should raise a ParseError if there is less than 3 arguments" do
+ lambda { @scope.function_regsubst(["foo", "bar"]) }.should(
+ raise_error(Puppet::ParseError))
+ end
+
+ it "should raise a ParseError if there is more than 5 arguments" do
+ lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "del", "x", "y"]) }.should(
+ raise_error(Puppet::ParseError))
+ end
+
+
+ it "should raise a ParseError when given a bad flag" do
+ lambda { @scope.function_regsubst(["foo", "bar", "gazonk", "X"]) }.should(
+ raise_error(Puppet::ParseError))
+ end
+
+ it "should handle groups" do
+ result = @scope.function_regsubst(
+ [ '130.236.254.10',
+ '^([0-9]+)[.]([0-9]+)[.]([0-9]+)[.]([0-9]+)$',
+ '\4-\3-\2-\1'
+ ])
+ result.should(eql("10-254-236-130"))
+ end
+
+ it "should handle simple regexps" do
+ result = @scope.function_regsubst(
+ [ "the monkey breaks banana trees",
+ "b[an]*a",
+ "coconut"
+ ])
+ result.should(eql("the monkey breaks coconut trees"))
+ end
+
+ it "should handle case-sensitive regexps" do
+ result = @scope.function_regsubst(
+ [ "the monkey breaks baNAna trees",
+ "b[an]+a",
+ "coconut"
+ ])
+ result.should(eql("the monkey breaks baNAna trees"))
+ end
+
+ it "should handle case-insensitive regexps" do
+ result = @scope.function_regsubst(
+ [ "the monkey breaks baNAna trees",
+ "b[an]+a",
+ "coconut",
+ "I"
+ ])
+ result.should(eql("the monkey breaks coconut trees"))
+ end
+
+ it "should handle global substitutions" do
+ result = @scope.function_regsubst(
+ [ "the monkey breaks\tbanana trees",
+ "[ \t]",
+ "--",
+ "G"
+ ])
+ result.should(eql("the--monkey--breaks--banana--trees"))
+ end
+
+ it "should handle global substitutions with groups" do
+ result = @scope.function_regsubst(
+ [ '130.236.254.10',
+ '([0-9]+)',
+ '<\1>',
+ 'G'
+ ])
+ result.should(eql('<130>.<236>.<254>.<10>'))
+ end
+
+end
diff --git a/spec/unit/parser/functions/sprintf.rb b/spec/unit/parser/functions/sprintf.rb
new file mode 100644
index 000000000..8654b18fc
--- /dev/null
+++ b/spec/unit/parser/functions/sprintf.rb
@@ -0,0 +1,42 @@
+#! /usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+describe "the sprintf function" do
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new()
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("sprintf").should == "function_sprintf"
+ end
+
+ it "should raise a ParseError if there is less than 1 argument" do
+ lambda { @scope.function_sprintf([]) }.should(
+ raise_error(Puppet::ParseError))
+ end
+
+ it "should format integers" do
+ result = @scope.function_sprintf(["%+05d", "23"])
+ result.should(eql("+0023"))
+ end
+
+ it "should format floats" do
+ result = @scope.function_sprintf(["%+.2f", "2.7182818284590451"])
+ result.should(eql("+2.72"))
+ end
+
+ it "should format large floats" do
+ result = @scope.function_sprintf(["%+.2e", "27182818284590451"])
+ result.should(eql("+2.72e+16"))
+ end
+
+ it "should perform more complex formatting" do
+ result = @scope.function_sprintf(
+ [ "<%.8s:%#5o %#8X (%-8s)>",
+ "overlongstring", "23", "48879", "foo" ])
+ result.should(eql("<overlong: 027 0XBEEF (foo )>"))
+ end
+
+end
diff --git a/spec/unit/provider/augeas/augeas.rb b/spec/unit/provider/augeas/augeas.rb
index 083448b4a..affc66676 100644
--- a/spec/unit/provider/augeas/augeas.rb
+++ b/spec/unit/provider/augeas/augeas.rb
@@ -285,32 +285,42 @@ describe provider_class do
@augeas.expects(:clear).with("/foo/Jar/Jar")
@augeas.expects(:save).returns(true)
@provider.execute_changes.should == :executed
- end
+ end
+
- it "should handle insert commands" do
- command = [["insert", "/Jar/Jar"]]
+ it "should handle ins commands with before" do
+ command = [["ins", "Binks", "before /Jar/Jar"]]
context = "/foo"
@resource.expects(:[]).times(2).returns(command).then.returns(context)
- @augeas.expects(:insert).with("/foo/Jar/Jar")
+ @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", true)
@augeas.expects(:save).returns(true)
@provider.execute_changes.should == :executed
end
- it "should handle ins commands" do
- command = [["ins", "/Jar/Jar"]]
+ it "should handle ins commands with before" do
+ command = [["ins", "Binks", "after /Jar/Jar"]]
context = "/foo"
@resource.expects(:[]).times(2).returns(command).then.returns(context)
- @augeas.expects(:insert).with("/foo/Jar/Jar")
+ @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false)
@augeas.expects(:save).returns(true)
@provider.execute_changes.should == :executed
end
+ it "should handle ins with no context" do
+ command = [["ins", "Binks", "after /Jar/Jar"]]
+ context = "" # this is the default
+ @resource.expects(:[]).times(2).returns(command).then.returns(context)
+ @augeas.expects(:insert).with("/Jar/Jar", "Binks", false)
+ @augeas.expects(:save).returns(true)
+ @provider.execute_changes.should == :executed
+ end
+
it "should handle multiple commands" do
- command = [["ins", "/Jar/Jar"], ["clear", "/Jar/Jar"]]
+ command = [["ins", "Binks", "after /Jar/Jar"], ["clear", "/Jar/Jar"]]
context = "/foo"
@resource.expects(:[]).times(2).returns(command).then.returns(context)
- @augeas.expects(:insert).with("/foo/Jar/Jar")
- @augeas.expects(:clear).with("/foo/Jar/Jar")
+ @augeas.expects(:insert).with("/foo/Jar/Jar", "Binks", false)
+ @augeas.expects(:clear).with("/foo/Jar/Jar")
@augeas.expects(:save).returns(true)
@provider.execute_changes.should == :executed
end
diff --git a/spec/unit/provider/parsedfile.rb b/spec/unit/provider/parsedfile.rb
index 05e9de3ab..11a91c8d7 100755
--- a/spec/unit/provider/parsedfile.rb
+++ b/spec/unit/provider/parsedfile.rb
@@ -47,4 +47,40 @@ describe Puppet::Provider::ParsedFile do
@class.instances
end
end
+
+ describe "when flushing a file's records to disk" do
+ before do
+ # This way we start with some @records, like we would in real life.
+ @class.stubs(:retrieve).returns []
+ @class.default_target = "/foo/bar"
+ @class.initvars
+ @class.prefetch
+
+ @filetype = mock 'filetype'
+ Puppet::Util::FileType.filetype(:flat).expects(:new).with("/my/file").returns @filetype
+
+ @filetype.stubs(:write)
+ end
+
+ it "should back up the file being written" do
+ @filetype.expects(:backup)
+
+ @class.flush_target("/my/file")
+ end
+
+ it "should not back up the file more than once between calls to 'prefetch'" do
+ @filetype.expects(:backup).once
+
+ @class.flush_target("/my/file")
+ @class.flush_target("/my/file")
+ end
+
+ it "should back the file up again once the file has been reread" do
+ @filetype.expects(:backup).times(2)
+
+ @class.flush_target("/my/file")
+ @class.prefetch
+ @class.flush_target("/my/file")
+ end
+ end
end
diff --git a/spec/unit/util/autoload.rb b/spec/unit/util/autoload.rb
new file mode 100755
index 000000000..ff717d6c5
--- /dev/null
+++ b/spec/unit/util/autoload.rb
@@ -0,0 +1,39 @@
+#!/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/autoload'
+
+describe Puppet::Util::Autoload do
+ before do
+ @autoload = Puppet::Util::Autoload.new("foo", "tmp")
+
+ @autoload.stubs(:eachdir).yields "/my/dir"
+ end
+
+ describe "when loading a file" do
+ [RuntimeError, LoadError, SyntaxError].each do |error|
+ it "should not die an if a #{error.to_s} exception is thrown" do
+ FileTest.stubs(:exists?).returns true
+
+ Kernel.expects(:load).raises error
+
+ lambda { @autoload.load("foo") }.should_not raise_error
+ end
+ end
+ end
+
+ describe "when loading all files" do
+ before do
+ Dir.stubs(:glob).returns "file.rb"
+ end
+
+ [RuntimeError, LoadError, SyntaxError].each do |error|
+ it "should not die an if a #{error.to_s} exception is thrown" do
+ Kernel.expects(:require).raises error
+
+ lambda { @autoload.loadall }.should_not raise_error
+ end
+ end
+ end
+end
diff --git a/spec/unit/util/filetype.rb b/spec/unit/util/filetype.rb
new file mode 100644
index 000000000..0506b6b47
--- /dev/null
+++ b/spec/unit/util/filetype.rb
@@ -0,0 +1,110 @@
+#!/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/filetype'
+
+# XXX Import all of the tests into this file.
+describe Puppet::Util::FileType do
+ describe "when backing up a file" do
+ before do
+ @file = Puppet::Util::FileType.filetype(:flat).new("/my/file")
+ end
+
+ it "should do nothing if the file does not exist" do
+ File.expects(:exists?).with("/my/file").returns false
+ @file.expects(:bucket).never
+ @file.backup
+ end
+
+ it "should use its filebucket to backup the file if it exists" do
+ File.expects(:exists?).with("/my/file").returns true
+
+ bucket = mock 'bucket'
+ bucket.expects(:backup).with("/my/file")
+
+ @file.expects(:bucket).returns bucket
+ @file.backup
+ end
+
+ it "should use the filebucket named 'puppet' if it finds one" do
+ bucket = mock 'bucket'
+ bucket.expects(:bucket).returns "mybucket"
+
+ Puppet::Type.type(:filebucket).expects(:[]).with("puppet").returns bucket
+
+ @file.bucket.should == "mybucket"
+ end
+
+ it "should use the default filebucket if none named 'puppet' is found" do
+ bucket = mock 'bucket'
+ bucket.expects(:bucket).returns "mybucket"
+
+ Puppet::Type.type(:filebucket).expects(:[]).with("puppet").returns nil
+ Puppet::Type.type(:filebucket).expects(:mkdefaultbucket).returns bucket
+
+ @file.bucket.should == "mybucket"
+ end
+ end
+
+ describe "the flat filetype" do
+ before do
+ @type = Puppet::Util::FileType.filetype(:flat)
+ end
+ it "should exist" do
+ @type.should_not be_nil
+ end
+
+ describe "when the file already exists" do
+ it "should return the file's contents when asked to read it" do
+ file = @type.new("/my/file")
+ File.expects(:exist?).with("/my/file").returns true
+ File.expects(:read).with("/my/file").returns "my text"
+
+ file.read.should == "my text"
+ end
+
+ it "should unlink the file when asked to remove it" do
+ file = @type.new("/my/file")
+ File.expects(:exist?).with("/my/file").returns true
+ File.expects(:unlink).with("/my/file")
+
+ file.remove
+ end
+ end
+
+ describe "when the file does not exist" do
+ it "should return an empty string when asked to read the file" do
+ file = @type.new("/my/file")
+ File.expects(:exist?).with("/my/file").returns false
+
+ file.read.should == ""
+ end
+ end
+
+ describe "when writing the file" do
+ before do
+ @file = @type.new("/my/file")
+ FileUtils.stubs(:cp)
+
+ @tempfile = stub 'tempfile', :print => nil, :close => nil, :flush => nil, :path => "/other/file"
+ Tempfile.stubs(:new).returns @tempfile
+ end
+
+ it "should first create a temp file and copy its contents over to the file location" do
+ Tempfile.expects(:new).with("puppet").returns @tempfile
+ @tempfile.expects(:print).with("my text")
+ @tempfile.expects(:flush)
+ @tempfile.expects(:close)
+ FileUtils.expects(:cp).with(@tempfile.path, "/my/file")
+
+ @file.write "my text"
+ end
+
+ it "should set the selinux default context on the file" do
+ @file.expects(:set_selinux_default_context).with("/my/file")
+ @file.write "eh"
+ end
+ end
+ end
+end