summaryrefslogtreecommitdiff
path: root/spec/unit
diff options
context:
space:
mode:
authorStig Sandbeck Mathisen <ssm@debian.org>2012-01-26 11:22:40 +0100
committerStig Sandbeck Mathisen <ssm@debian.org>2012-01-26 11:22:40 +0100
commitc17b3ba16e7013f06416f10b8752ef783f048717 (patch)
tree790f13f167199b954007e17d1c55a8d1b0218775 /spec/unit
parent32af6143486ceb24a93636445d1883f5fe2299d7 (diff)
downloadpuppet-upstream/2.7.10.tar.gz
Imported Upstream version 2.7.10upstream/2.7.10
Diffstat (limited to 'spec/unit')
-rw-r--r--spec/unit/agent/disabler_spec.rb60
-rwxr-xr-xspec/unit/agent/locker_spec.rb12
-rwxr-xr-xspec/unit/agent_spec.rb8
-rwxr-xr-xspec/unit/application/agent_spec.rb65
-rwxr-xr-xspec/unit/application/apply_spec.rb13
-rwxr-xr-xspec/unit/application/cert_spec.rb2
-rwxr-xr-xspec/unit/application_spec.rb6
-rwxr-xr-xspec/unit/configurer/downloader_spec.rb39
-rwxr-xr-xspec/unit/configurer/fact_handler_spec.rb34
-rwxr-xr-xspec/unit/configurer_spec.rb18
-rw-r--r--spec/unit/face/instrumentation_data.rb7
-rw-r--r--spec/unit/face/instrumentation_listener.rb38
-rw-r--r--spec/unit/face/instrumentation_probe.rb21
-rw-r--r--spec/unit/face/module_spec.rb3
-rwxr-xr-xspec/unit/face/node_spec.rb222
-rwxr-xr-xspec/unit/file_serving/content_spec.rb4
-rwxr-xr-xspec/unit/indirector/facts/facter_spec.rb28
-rwxr-xr-xspec/unit/indirector/facts/inventory_active_record_spec.rb18
-rw-r--r--spec/unit/indirector/instrumentation_data/local_spec.rb52
-rw-r--r--spec/unit/indirector/instrumentation_data/rest_spec.rb11
-rw-r--r--spec/unit/indirector/instrumentation_listener/local_spec.rb65
-rw-r--r--spec/unit/indirector/instrumentation_listener/rest_spec.rb11
-rw-r--r--spec/unit/indirector/instrumentation_probe/local_spec.rb65
-rw-r--r--spec/unit/indirector/instrumentation_probe/rest_spec.rb11
-rwxr-xr-xspec/unit/module_spec.rb164
-rw-r--r--spec/unit/module_tool/application_spec.rb29
-rw-r--r--spec/unit/module_tool/metadata_spec.rb11
-rw-r--r--spec/unit/module_tool/repository_spec.rb52
-rw-r--r--spec/unit/module_tool/uninstaller_spec.rb44
-rw-r--r--spec/unit/module_tool_spec.rb38
-rwxr-xr-xspec/unit/network/http/api/v1_spec.rb4
-rwxr-xr-xspec/unit/node/environment_spec.rb134
-rwxr-xr-xspec/unit/parser/ast/asthash_spec.rb3
-rwxr-xr-xspec/unit/parser/ast/leaf_spec.rb16
-rwxr-xr-xspec/unit/parser/functions/create_resources_spec.rb25
-rwxr-xr-xspec/unit/property/keyvalue_spec.rb7
-rwxr-xr-xspec/unit/provider/augeas/augeas_spec.rb4
-rwxr-xr-xspec/unit/provider/group/pw_spec.rb81
-rwxr-xr-xspec/unit/provider/nameservice/directoryservice_spec.rb102
-rwxr-xr-xspec/unit/provider/package/pip_spec.rb7
-rwxr-xr-xspec/unit/provider/package/yum_spec.rb46
-rwxr-xr-xspec/unit/provider/service/debian_spec.rb15
-rwxr-xr-xspec/unit/provider/service/launchd_spec.rb91
-rwxr-xr-xspec/unit/provider/service/smf_spec.rb6
-rwxr-xr-xspec/unit/provider/user/pw_spec.rb183
-rwxr-xr-xspec/unit/provider/user/windows_adsi_spec.rb1
-rwxr-xr-xspec/unit/rails_spec.rb247
-rwxr-xr-xspec/unit/reports/store_spec.rb20
-rwxr-xr-xspec/unit/ssl/certificate_factory_spec.rb6
-rwxr-xr-xspec/unit/ssl/host_spec.rb43
-rwxr-xr-xspec/unit/transaction/report_spec.rb30
-rwxr-xr-xspec/unit/transaction_spec.rb78
-rwxr-xr-xspec/unit/type/file/mode_spec.rb2
-rwxr-xr-xspec/unit/type/file/source_spec.rb31
-rwxr-xr-xspec/unit/type/file_spec.rb63
-rwxr-xr-xspec/unit/type/host_spec.rb527
-rwxr-xr-xspec/unit/type/schedule_spec.rb12
-rwxr-xr-xspec/unit/type_spec.rb29
-rw-r--r--spec/unit/util/anonymous_filelock_spec.rb78
-rwxr-xr-xspec/unit/util/execution_stub_spec.rb3
-rwxr-xr-xspec/unit/util/instrumentation/data_spec.rb44
-rw-r--r--spec/unit/util/instrumentation/indirection_probe_spec.rb19
-rwxr-xr-xspec/unit/util/instrumentation/instrumentable_spec.rb186
-rwxr-xr-xspec/unit/util/instrumentation/listener_spec.rb100
-rwxr-xr-xspec/unit/util/instrumentation/listeners/log_spec.rb34
-rwxr-xr-xspec/unit/util/instrumentation/listeners/performance_spec.rb36
-rwxr-xr-xspec/unit/util/instrumentation/listeners/process_name_spec.rb201
-rwxr-xr-xspec/unit/util/instrumentation_spec.rb181
-rw-r--r--spec/unit/util/pidlock_spec.rb182
-rwxr-xr-xspec/unit/util/queue/stomp_spec.rb13
-rwxr-xr-xspec/unit/util/rdoc/parser_spec.rb2
-rw-r--r--spec/unit/util/reference_spec.rb22
-rw-r--r--spec/unit/util/retryaction_spec.rb62
-rwxr-xr-xspec/unit/util/suidmanager_spec.rb19
-rwxr-xr-xspec/unit/util/symbolic_file_mode_spec.rb182
-rwxr-xr-xspec/unit/util/zaml_spec.rb37
76 files changed, 3662 insertions, 703 deletions
diff --git a/spec/unit/agent/disabler_spec.rb b/spec/unit/agent/disabler_spec.rb
new file mode 100644
index 000000000..5e43cf964
--- /dev/null
+++ b/spec/unit/agent/disabler_spec.rb
@@ -0,0 +1,60 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+require 'puppet/agent'
+require 'puppet/agent/locker'
+
+class LockerTester
+ include Puppet::Agent::Disabler
+end
+
+describe Puppet::Agent::Disabler do
+ before do
+ @locker = LockerTester.new
+ @locker.stubs(:lockfile_path).returns "/my/lock"
+ end
+
+ it "should use an AnonymousFilelock instance as its disable_lockfile" do
+ @locker.disable_lockfile.should be_instance_of(Puppet::Util::AnonymousFilelock)
+ end
+
+ it "should use 'lockfile_path' to determine its disable_lockfile path" do
+ @locker.expects(:lockfile_path).returns "/my/lock"
+ lock = Puppet::Util::AnonymousFilelock.new("/my/lock")
+ Puppet::Util::AnonymousFilelock.expects(:new).with("/my/lock.disabled").returns lock
+
+ @locker.disable_lockfile
+ end
+
+ it "should reuse the same lock file each time" do
+ @locker.disable_lockfile.should equal(@locker.disable_lockfile)
+ end
+
+ it "should lock the anonymous lock when disabled" do
+ @locker.disable_lockfile.expects(:lock)
+
+ @locker.disable
+ end
+
+ it "should disable with a message" do
+ @locker.disable_lockfile.expects(:lock).with("disabled because")
+
+ @locker.disable("disabled because")
+ end
+
+ it "should unlock the anonymous lock when enabled" do
+ @locker.disable_lockfile.expects(:unlock)
+
+ @locker.enable
+ end
+
+ it "should check the lock if it is disabled" do
+ @locker.disable_lockfile.expects(:locked?)
+
+ @locker.disabled?
+ end
+
+ it "should report the disable message when disabled" do
+ @locker.disable_lockfile.expects(:message).returns("message")
+ @locker.disable_message.should == "message"
+ end
+end
diff --git a/spec/unit/agent/locker_spec.rb b/spec/unit/agent/locker_spec.rb
index 341859e3b..9b530c0d8 100755
--- a/spec/unit/agent/locker_spec.rb
+++ b/spec/unit/agent/locker_spec.rb
@@ -29,18 +29,6 @@ describe Puppet::Agent::Locker do
@locker.lockfile.should equal(@locker.lockfile)
end
- it "should use the lock file to anonymously lock the process when disabled" do
- @locker.lockfile.expects(:lock).with(:anonymous => true)
-
- @locker.disable
- end
-
- it "should use the lock file to anonymously unlock the process when enabled" do
- @locker.lockfile.expects(:unlock).with(:anonymous => true)
-
- @locker.enable
- end
-
it "should have a method that yields when a lock is attained" do
@locker.lockfile.expects(:lock).returns true
diff --git a/spec/unit/agent_spec.rb b/spec/unit/agent_spec.rb
index d955868a0..9e2840c58 100755
--- a/spec/unit/agent_spec.rb
+++ b/spec/unit/agent_spec.rb
@@ -24,6 +24,7 @@ describe Puppet::Agent do
# So we don't actually try to hit the filesystem.
@agent.stubs(:lock).yields
+ @agent.stubs(:disabled?).returns(false)
# make Puppet::Application safe for stubbing; restore in an :after block; silence warnings for this.
without_warnings { Puppet::Application = Class.new(Puppet::Application) }
@@ -76,6 +77,7 @@ describe Puppet::Agent do
describe "when being run" do
before do
+ AgentTestClient.stubs(:lockfile_path).returns "/my/lock"
@agent.stubs(:running?).returns false
end
@@ -92,6 +94,12 @@ describe Puppet::Agent do
@agent.run
end
+ it "should do nothing if disabled" do
+ @agent.expects(:disabled?).returns(true)
+ AgentTestClient.expects(:new).never
+ @agent.run
+ end
+
it "should use Puppet::Application.controlled_run to manage process state behavior" do
calls = sequence('calls')
Puppet::Application.expects(:controlled_run).yields.in_sequence(calls)
diff --git a/spec/unit/application/agent_spec.rb b/spec/unit/application/agent_spec.rb
index 6d31ec34a..13be1a5af 100755
--- a/spec/unit/application/agent_spec.rb
+++ b/spec/unit/application/agent_spec.rb
@@ -91,7 +91,7 @@ describe Puppet::Application::Agent do
@puppetd.command_line.stubs(:args).returns([])
end
- [:centrallogging, :disable, :enable, :debug, :fqdn, :test, :verbose, :digest].each do |option|
+ [:centrallogging, :enable, :debug, :fqdn, :test, :verbose, :digest].each do |option|
it "should declare handle_#{option} method" do
@puppetd.should respond_to("handle_#{option}".to_sym)
end
@@ -102,6 +102,24 @@ describe Puppet::Application::Agent do
end
end
+ describe "when handling --disable" do
+ it "should declare handle_disable method" do
+ @puppetd.should respond_to(:handle_disable)
+ end
+
+ it "should set disable to true" do
+ @puppetd.options.stubs(:[]=)
+ @puppetd.options.expects(:[]=).with(:disable, true)
+ @puppetd.handle_disable('')
+ end
+
+ it "should store disable message" do
+ @puppetd.options.stubs(:[]=)
+ @puppetd.options.expects(:[]=).with(:disable_message, "message")
+ @puppetd.handle_disable('message')
+ end
+ end
+
it "should set an existing handler on server" do
Puppet::Network::Handler.stubs(:handler).with("handler").returns(true)
@@ -349,6 +367,20 @@ describe Puppet::Application::Agent do
end
end
+ it "should pass the disable message when disabling" do
+ @puppetd.options.stubs(:[]).with(:disable).returns(true)
+ @puppetd.options.stubs(:[]).with(:disable_message).returns("message")
+ @agent.expects(:disable).with("message")
+ expect { @puppetd.enable_disable_client(@agent) }.to exit_with 0
+ end
+
+ it "should pass the default disable message when disabling without a message" do
+ @puppetd.options.stubs(:[]).with(:disable).returns(true)
+ @puppetd.options.stubs(:[]).with(:disable_message).returns(nil)
+ @agent.expects(:disable).with("reason not specified")
+ expect { @puppetd.enable_disable_client(@agent) }.to exit_with 0
+ end
+
it "should finally exit" do
expect { @puppetd.enable_disable_client(@agent) }.to exit_with 0
end
@@ -437,6 +469,32 @@ describe Puppet::Application::Agent do
@puppetd.setup_listen
end
end
+
+ describe "when setting up for fingerprint" do
+ before(:each) do
+ @puppetd.options.stubs(:[]).with(:fingerprint).returns(true)
+ end
+
+ it "should not setup as an agent" do
+ @puppetd.expects(:setup_agent).never
+ @puppetd.setup
+ end
+
+ it "should not create an agent" do
+ Puppet::Agent.stubs(:new).with(Puppet::Configurer).never
+ @puppetd.setup
+ end
+
+ it "should not daemonize" do
+ @daemon.expects(:daemonize).never
+ @puppetd.setup
+ end
+
+ it "should setup our certificate host" do
+ @puppetd.expects(:setup_host)
+ @puppetd.setup
+ end
+ end
end
@@ -497,6 +555,11 @@ describe Puppet::Application::Agent do
expect { @puppetd.onetime }.to exit_with 0
end
+ it "should stop the daemon" do
+ @daemon.expects(:stop).with(:exit => false)
+ expect { @puppetd.onetime }.to exit_with 0
+ end
+
describe "and --detailed-exitcodes" do
before :each do
@puppetd.options.stubs(:[]).with(:detailed_exitcodes).returns(true)
diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb
index b12c4fae9..07a39223c 100755
--- a/spec/unit/application/apply_spec.rb
+++ b/spec/unit/application/apply_spec.rb
@@ -20,7 +20,7 @@ describe Puppet::Application::Apply do
Puppet::Node.indirection.cache_class = nil
end
- [:debug,:loadclasses,:verbose,:use_nodes,:detailed_exitcodes].each do |option|
+ [:debug,:loadclasses,:verbose,:use_nodes,:detailed_exitcodes,:catalog].each do |option|
it "should declare handle_#{option} method" do
@apply.should respond_to("handle_#{option}".to_sym)
end
@@ -53,6 +53,17 @@ describe Puppet::Application::Apply do
@apply.handle_logdest("console")
end
+
+ it "should deprecate --apply" do
+ Puppet.expects(:warning).with do |arg|
+ arg.match(/--apply is deprecated/)
+ end
+
+ command_line = Puppet::Util::CommandLine.new('puppet', ['apply', '--apply', 'catalog.json'])
+ apply = Puppet::Application::Apply.new(command_line)
+ apply.stubs(:run_command)
+ apply.run
+ end
end
describe "during setup" do
diff --git a/spec/unit/application/cert_spec.rb b/spec/unit/application/cert_spec.rb
index 300234c2b..8f0021ae6 100755
--- a/spec/unit/application/cert_spec.rb
+++ b/spec/unit/application/cert_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
require 'puppet/application/cert'
-describe Puppet::Application::Cert, :'fails_on_ruby_1.9.2' => true do
+describe Puppet::Application::Cert => true do
before :each do
@cert_app = Puppet::Application[:cert]
Puppet::Util::Log.stubs(:newdestination)
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index fd93ceb00..591358efb 100755
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -8,6 +8,7 @@ require 'getoptlong'
describe Puppet::Application do
before do
+ Puppet::Util::Instrumentation.stubs(:init)
@app = Class.new(Puppet::Application).new
@appclass = @app.class
@@ -117,6 +118,11 @@ describe Puppet::Application do
@app.run_command
end
+ it "should initialize the Puppet Instrumentation layer on creation" do
+ Puppet::Util::Instrumentation.expects(:init)
+ Class.new(Puppet::Application).new
+ end
+
describe 'when invoking clear!' do
before :each do
Puppet::Application.run_status = :stop_requested
diff --git a/spec/unit/configurer/downloader_spec.rb b/spec/unit/configurer/downloader_spec.rb
index 215ef897f..69e5e6bf9 100755
--- a/spec/unit/configurer/downloader_spec.rb
+++ b/spec/unit/configurer/downloader_spec.rb
@@ -60,16 +60,35 @@ describe Puppet::Configurer::Downloader do
@dler.file
end
- it "should always set the owner to the current UID" do
- Process.expects(:uid).returns 51
- Puppet::Type.type(:file).expects(:new).with { |opts| opts[:owner] == 51 }
- @dler.file
- end
-
- it "should always set the group to the current GID" do
- Process.expects(:gid).returns 61
- Puppet::Type.type(:file).expects(:new).with { |opts| opts[:group] == 61 }
- @dler.file
+ describe "on POSIX" do
+ before :each do
+ Puppet.features.stubs(:microsoft_windows?).returns false
+ end
+
+ it "should always set the owner to the current UID" do
+ Process.expects(:uid).returns 51
+ Puppet::Type.type(:file).expects(:new).with { |opts| opts[:owner] == 51 }
+ @dler.file
+ end
+
+ it "should always set the group to the current GID" do
+ Process.expects(:gid).returns 61
+ Puppet::Type.type(:file).expects(:new).with { |opts| opts[:group] == 61 }
+ @dler.file
+ end
+ end
+
+ describe "on Windows", :if => Puppet.features.microsoft_windows? do
+ it "should always set the owner to the current user" do
+ Sys::Admin.expects(:get_login).returns 'foo'
+ Puppet::Type.type(:file).expects(:new).with { |opts| opts[:owner] == 'foo' }
+ @dler.file
+ end
+
+ it "should always set the group to nobody" do
+ Puppet::Type.type(:file).expects(:new).with { |opts| opts[:group] == 'S-1-0-0' }
+ @dler.file
+ end
end
it "should always force the download" do
diff --git a/spec/unit/configurer/fact_handler_spec.rb b/spec/unit/configurer/fact_handler_spec.rb
index 4a3fe8b3b..41b4862ca 100755
--- a/spec/unit/configurer/fact_handler_spec.rb
+++ b/spec/unit/configurer/fact_handler_spec.rb
@@ -78,12 +78,6 @@ describe Puppet::Configurer::FactHandler do
Puppet[:node_name_value].should == 'other_node_name'
end
- it "should reload Facter before finding facts" do
- @facthandler.expects(:reload_facter)
-
- @facthandler.find_facts
- end
-
it "should fail if finding facts fails" do
Puppet[:trace] = false
Puppet[:certname] = "myhost"
@@ -93,6 +87,11 @@ describe Puppet::Configurer::FactHandler do
end
end
+ it "should only load fact plugins once" do
+ Puppet::Node::Facts.indirection.expects(:find).once
+ @facthandler.find_facts
+ end
+
it "should warn about factsync deprecation when factsync is enabled" do
Puppet::Configurer::Downloader.stubs(:new).returns mock("downloader", :evaluate => nil)
@@ -145,27 +144,4 @@ describe Puppet::Configurer::FactHandler do
@facthandler.facts_for_uploading
end
-
- describe "when reloading Facter" do
- before do
- Facter.stubs(:clear)
- Facter.stubs(:load)
- Facter.stubs(:loadfacts)
- end
-
- it "should clear Facter" do
- Facter.expects(:clear)
- @facthandler.reload_facter
- end
-
- it "should load all Facter facts" do
- Facter.expects(:loadfacts)
- @facthandler.reload_facter
- end
-
- it "should use the Facter terminus load all Puppet Fact plugins" do
- Puppet::Node::Facts::Facter.expects(:load_fact_plugins)
- @facthandler.reload_facter
- end
- end
end
diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb
index 5c660cc31..5afed1f58 100755
--- a/spec/unit/configurer_spec.rb
+++ b/spec/unit/configurer_spec.rb
@@ -407,33 +407,33 @@ describe Puppet::Configurer do
end
describe "when saving the summary report file" do
+ include PuppetSpec::Files
+
before do
Puppet.settings.stubs(:use).returns(true)
@configurer = Puppet::Configurer.new
- @report = stub 'report'
- @trans = stub 'transaction'
- @lastrunfd = stub 'lastrunfd'
- Puppet::Util::FileLocking.stubs(:writelock).yields(@lastrunfd)
+ @report = stub 'report', :raw_summary => {}
+
+ Puppet[:lastrunfile] = tmpfile('last_run_file')
end
- it "should write the raw summary to the lastrunfile setting value" do
- Puppet::Util::FileLocking.expects(:writelock).with(Puppet[:lastrunfile], 0660)
+ it "should write the last run file" do
@configurer.save_last_run_summary(@report)
+ FileTest.exists?(Puppet[:lastrunfile]).should be_true
end
it "should write the raw summary as yaml" do
@report.expects(:raw_summary).returns("summary")
- @lastrunfd.expects(:print).with(YAML.dump("summary"))
@configurer.save_last_run_summary(@report)
+ File.read(Puppet[:lastrunfile]).should == YAML.dump("summary")
end
it "should log but not fail if saving the last run summary fails" do
- Puppet::Util::FileLocking.expects(:writelock).raises "exception"
+ Puppet[:lastrunfile] = "/dev/null/inexistant"
Puppet.expects(:err)
lambda { @configurer.save_last_run_summary(@report) }.should_not raise_error
end
-
end
describe "when retrieving a catalog" do
diff --git a/spec/unit/face/instrumentation_data.rb b/spec/unit/face/instrumentation_data.rb
new file mode 100644
index 000000000..2d4cc74f6
--- /dev/null
+++ b/spec/unit/face/instrumentation_data.rb
@@ -0,0 +1,7 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+require 'puppet/face'
+
+describe Puppet::Face[:instrumentation_data, '0.0.1'] do
+ it_should_behave_like "an indirector face"
+end
diff --git a/spec/unit/face/instrumentation_listener.rb b/spec/unit/face/instrumentation_listener.rb
new file mode 100644
index 000000000..87f218855
--- /dev/null
+++ b/spec/unit/face/instrumentation_listener.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+require 'puppet/face'
+
+describe Puppet::Face[:instrumentation_listener, '0.0.1'] do
+ it_should_behave_like "an indirector face"
+
+ [:enable, :disable].each do |m|
+ describe "when running ##{m}" do
+ before(:each) do
+ @listener = stub_everything 'listener'
+ Puppet::Face[:instrumentation_listener, '0.0.1'].stubs(:find).returns(@listener)
+ Puppet::Face[:instrumentation_listener, '0.0.1'].stubs(:save)
+ Puppet::Util::Instrumentation::Listener.indirection.stubs(:terminus_class=)
+ end
+
+ it "should force the REST terminus" do
+ Puppet::Util::Instrumentation::Listener.indirection.expects(:terminus_class=).with(:rest)
+ subject.send(m, "dummy")
+ end
+
+ it "should find the named listener" do
+ Puppet::Face[:instrumentation_listener, '0.0.1'].expects(:find).with("dummy").returns(@listener)
+ subject.send(m, "dummy")
+ end
+
+ it "should #{m} the named listener" do
+ @listener.expects(:enabled=).with( m == :enable )
+ subject.send(m, "dummy")
+ end
+
+ it "should save finally the listener" do
+ Puppet::Face[:instrumentation_listener, '0.0.1'].expects(:save).with(@listener)
+ subject.send(m, "dummy")
+ end
+ end
+ end
+end
diff --git a/spec/unit/face/instrumentation_probe.rb b/spec/unit/face/instrumentation_probe.rb
new file mode 100644
index 000000000..3e475906d
--- /dev/null
+++ b/spec/unit/face/instrumentation_probe.rb
@@ -0,0 +1,21 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+require 'puppet/face'
+
+describe Puppet::Face[:instrumentation_probe, '0.0.1'] do
+ it_should_behave_like "an indirector face"
+
+ describe 'when running #enable' do
+ it 'should invoke #save' do
+ subject.expects(:save).with(nil)
+ subject.enable('hostname')
+ end
+ end
+
+ describe 'when running #disable' do
+ it 'should invoke #destroy' do
+ subject.expects(:destroy).with(nil)
+ subject.disable('hostname')
+ end
+ end
+end
diff --git a/spec/unit/face/module_spec.rb b/spec/unit/face/module_spec.rb
new file mode 100644
index 000000000..33e486e5a
--- /dev/null
+++ b/spec/unit/face/module_spec.rb
@@ -0,0 +1,3 @@
+# For face related tests, look in the spec/unit/faces/module folder.
+# For integration tests, which test the behavior of module, look in the
+# spec/unit/integration folder.
diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb
index cb36e58a4..b126af6bb 100755
--- a/spec/unit/face/node_spec.rb
+++ b/spec/unit/face/node_spec.rb
@@ -14,9 +14,7 @@ describe Puppet::Face[:node, '0.0.1'] do
"cached_facts" => ['hostname'],
"cached_node" => ['hostname'],
"reports" => ['hostname'],
-
- # Support for cleaning storeconfigs has been temporarily suspended.
- # "storeconfigs" => ['hostname', :unexport]
+ "storeconfigs" => ['hostname', :unexport]
}.each { |k, v| subject.expects("clean_#{k}".to_sym).with(*v) }
subject.cleanup('hostname', :unexport)
end
@@ -158,114 +156,116 @@ describe Puppet::Face[:node, '0.0.1'] do
end
end
- # describe "when cleaning storeconfigs entries for host", :if => Puppet.features.rails? do
- # before :each do
- # # Stub this so we don't need access to the DB
- # require 'puppet/rails/host'
- #
- # Puppet.stubs(:[]).with(:storeconfigs).returns(true)
- #
- # Puppet::Rails.stubs(:connect)
- # @rails_node = stub_everything 'rails_node'
- # Puppet::Rails::Host.stubs(:find_by_name).returns(@rails_node)
- # end
- #
- # it "should connect to the database" do
- # Puppet::Rails.expects(:connect)
- # subject.clean_storeconfigs(@host, false)
- # end
- #
- # it "should find the right host entry" do
- # Puppet::Rails::Host.expects(:find_by_name).with(@host).returns(@rails_node)
- # subject.clean_storeconfigs(@host, false)
- # end
- #
- # describe "without unexport" do
- # it "should remove the host and it's content" do
- # @rails_node.expects(:destroy)
- # subject.clean_storeconfigs(@host, false)
- # end
- # end
- #
- # describe "with unexport" do
- # before :each do
- # @rails_node.stubs(:id).returns(1234)
- #
- # @type = stub_everything 'type'
- # @type.stubs(:validattr?).with(:ensure).returns(true)
- #
- # @ensure_name = stub_everything 'ensure_name', :id => 23453
- # Puppet::Rails::ParamName.stubs(:find_or_create_by_name).returns(@ensure_name)
- #
- # @param_values = stub_everything 'param_values'
- # @resource = stub_everything 'resource', :param_values => @param_values, :restype => "File"
- # Puppet::Rails::Resource.stubs(:find).returns([@resource])
- # end
- #
- # it "should find all resources" do
- # Puppet::Rails::Resource.expects(:find).with(:all, {:include => {:param_values => :param_name}, :conditions => ["exported=? AND host_id=?", true, 1234]}).returns([])
- #
- # subject.clean_storeconfigs(@host, true)
- # end
- #
- # describe "with an exported native type" do
- # before :each do
- # Puppet::Type.stubs(:type).returns(@type)
- # @type.expects(:validattr?).with(:ensure).returns(true)
- # end
- #
- # it "should test a native type for ensure as an attribute" do
- # subject.clean_storeconfigs(@host, true)
- # end
- #
- # it "should delete the old ensure parameter" do
- # ensure_param = stub 'ensure_param', :id => 12345, :line => 12
- # @param_values.stubs(:find).returns(ensure_param)
- # Puppet::Rails::ParamValue.expects(:delete).with(12345);
- # subject.clean_storeconfigs(@host, true)
- # end
- #
- # it "should add an ensure => absent parameter" do
- # @param_values.expects(:create).with(:value => "absent",
- # :line => 0,
- # :param_name => @ensure_name)
- # subject.clean_storeconfigs(@host, true)
- # end
- # end
- #
- # describe "with an exported definition" do
- # it "should try to lookup a definition and test it for the ensure argument" do
- # Puppet::Type.stubs(:type).returns(nil)
- # definition = stub_everything 'definition', :arguments => { 'ensure' => 'present' }
- # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
- # subject.clean_storeconfigs(@host, true)
- # end
- # end
- #
- # it "should not unexport the resource of an unknown type" do
- # Puppet::Type.stubs(:type).returns(nil)
- # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
- # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
- # subject.clean_storeconfigs(@host)
- # end
- #
- # it "should not unexport the resource of a not ensurable native type" do
- # Puppet::Type.stubs(:type).returns(@type)
- # @type.expects(:validattr?).with(:ensure).returns(false)
- # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
- # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
- # subject.clean_storeconfigs(@host, true)
- # end
- #
- # it "should not unexport the resource of a not ensurable definition" do
- # Puppet::Type.stubs(:type).returns(nil)
- # definition = stub_everything 'definition', :arguments => { 'foobar' => 'someValue' }
- # Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
- # Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
- # subject.clean_storeconfigs(@host, true)
- # end
- # end
- # end
+ describe "when cleaning storeconfigs entries for host", :if => Puppet.features.rails? do
+ before :each do
+ # Stub this so we don't need access to the DB
+ require 'puppet/rails/host'
+
+ Puppet.stubs(:[]).with(:storeconfigs).returns(true)
+
+ Puppet::Rails.stubs(:connect)
+ @rails_node = stub_everything 'rails_node'
+ Puppet::Rails::Host.stubs(:find_by_name).returns(@rails_node)
+ end
+
+ it "should connect to the database" do
+ Puppet::Rails.expects(:connect)
+ subject.clean_storeconfigs(@host, false)
+ end
+
+ it "should find the right host entry" do
+ Puppet::Rails::Host.expects(:find_by_name).with(@host).returns(@rails_node)
+
+ subject.clean_storeconfigs(@host, false)
+ end
+
+ describe "without unexport" do
+ it "should remove the host and it's content" do
+ @rails_node.expects(:destroy)
+
+ subject.clean_storeconfigs(@host, false)
+ end
+ end
+
+ describe "with unexport" do
+ before :each do
+ @rails_node.stubs(:id).returns(1234)
+
+ @type = stub_everything 'type'
+ @type.stubs(:validattr?).with(:ensure).returns(true)
+
+ @ensure_name = stub_everything 'ensure_name', :id => 23453
+ Puppet::Rails::ParamName.stubs(:find_or_create_by_name).returns(@ensure_name)
+
+ @param_values = stub_everything 'param_values'
+ @resource = stub_everything 'resource', :param_values => @param_values, :restype => "File"
+ Puppet::Rails::Resource.stubs(:find).returns([@resource])
+ end
+
+ it "should find all resources" do
+ Puppet::Rails::Resource.expects(:find).with(:all, {:include => {:param_values => :param_name}, :conditions => ["exported=? AND host_id=?", true, 1234]}).returns([])
+
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ describe "with an exported native type" do
+ before :each do
+ Puppet::Type.stubs(:type).returns(@type)
+ @type.expects(:validattr?).with(:ensure).returns(true)
+ end
+
+ it "should test a native type for ensure as an attribute" do
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should delete the old ensure parameter" do
+ ensure_param = stub 'ensure_param', :id => 12345, :line => 12
+ @param_values.stubs(:find).returns(ensure_param)
+ Puppet::Rails::ParamValue.expects(:delete).with(12345);
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should add an ensure => absent parameter" do
+ @param_values.expects(:create).with(:value => "absent",
+ :line => 0,
+ :param_name => @ensure_name)
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+
+ describe "with an exported definition" do
+ it "should try to lookup a definition and test it for the ensure argument" do
+ Puppet::Type.stubs(:type).returns(nil)
+ definition = stub_everything 'definition', :arguments => { 'ensure' => 'present' }
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+
+ it "should not unexport the resource of an unkown type" do
+ Puppet::Type.stubs(:type).returns(nil)
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should not unexport the resource of a not ensurable native type" do
+ Puppet::Type.stubs(:type).returns(@type)
+ @type.expects(:validattr?).with(:ensure).returns(false)
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(nil)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host, true)
+ end
+
+ it "should not unexport the resource of a not ensurable definition" do
+ Puppet::Type.stubs(:type).returns(nil)
+ definition = stub_everything 'definition', :arguments => { 'foobar' => 'someValue' }
+ Puppet::Resource::TypeCollection.any_instance.expects(:find_definition).with('', "File").returns(definition)
+ Puppet::Rails::ParamName.expects(:find_or_create_by_name).never
+ subject.clean_storeconfigs(@host, true)
+ end
+ end
+ end
end
end
end
diff --git a/spec/unit/file_serving/content_spec.rb b/spec/unit/file_serving/content_spec.rb
index 335f0e701..c1627c18f 100755
--- a/spec/unit/file_serving/content_spec.rb
+++ b/spec/unit/file_serving/content_spec.rb
@@ -102,13 +102,13 @@ describe Puppet::FileServing::Content, "when returning the contents" do
it "should return the contents of the path if the file exists" do
File.expects(:stat).with(@path).returns stub("stat", :ftype => "file")
- File.expects(:read).with(@path).returns(:mycontent)
+ Puppet::Util.expects(:binread).with(@path).returns(:mycontent)
@content.content.should == :mycontent
end
it "should cache the returned contents" do
File.expects(:stat).with(@path).returns stub("stat", :ftype => "file")
- File.expects(:read).with(@path).returns(:mycontent)
+ Puppet::Util.expects(:binread).with(@path).returns(:mycontent)
@content.content
# The second run would throw a failure if the content weren't being cached.
diff --git a/spec/unit/indirector/facts/facter_spec.rb b/spec/unit/indirector/facts/facter_spec.rb
index 3b1574e52..0cb8037aa 100755
--- a/spec/unit/indirector/facts/facter_spec.rb
+++ b/spec/unit/indirector/facts/facter_spec.rb
@@ -21,14 +21,29 @@ describe Puppet::Node::Facts::Facter do
Puppet::Node::Facts::Facter.name.should == :facter
end
- it "should load facts on initialization" do
- Puppet::Node::Facts::Facter.expects(:load_fact_plugins)
- Puppet::Node::Facts::Facter.new
+ describe "when reloading Facter" do
+ before do
+ @facter_class = Puppet::Node::Facts::Facter
+ Facter.stubs(:clear)
+ Facter.stubs(:load)
+ Facter.stubs(:loadfacts)
+ end
+
+ it "should clear Facter" do
+ Facter.expects(:clear)
+ @facter_class.reload_facter
+ end
+
+ it "should load all Facter facts" do
+ Facter.expects(:loadfacts)
+ @facter_class.reload_facter
+ end
end
end
describe Puppet::Node::Facts::Facter do
before :each do
+ Puppet::Node::Facts::Facter.stubs(:reload_facter)
@facter = Puppet::Node::Facts::Facter.new
Facter.stubs(:to_hash).returns({})
@name = "me"
@@ -36,6 +51,13 @@ describe Puppet::Node::Facts::Facter do
end
describe Puppet::Node::Facts::Facter, " when finding facts" do
+ it "should reset and load facts" do
+ clear = sequence 'clear'
+ Puppet::Node::Facts::Facter.expects(:reload_facter).in_sequence(clear)
+ Puppet::Node::Facts::Facter.expects(:load_fact_plugins).in_sequence(clear)
+ @facter.find(@request)
+ end
+
it "should return a Facts instance" do
@facter.find(@request).should be_instance_of(Puppet::Node::Facts)
end
diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb b/spec/unit/indirector/facts/inventory_active_record_spec.rb
index 88e5e5359..43dcc7c6b 100755
--- a/spec/unit/indirector/facts/inventory_active_record_spec.rb
+++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb
@@ -38,10 +38,22 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r
end
describe "#save" do
+ let(:node) {
+ Puppet::Rails::InventoryNode.new(:name => "foo", :timestamp => Time.now)
+ }
+
+ let(:facts) {
+ Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
+ }
+
+ it "should retry on ActiveRecord error" do
+ Puppet::Rails::InventoryNode.expects(:create).twice.raises(ActiveRecord::StatementInvalid).returns node
+
+ Puppet::Node::Facts.indirection.save(facts)
+ end
+
it "should use an existing node if possible" do
- node = Puppet::Rails::InventoryNode.new(:name => "foo", :timestamp => Time.now)
node.save
- facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
Puppet::Node::Facts.indirection.save(facts)
Puppet::Rails::InventoryNode.count.should == 1
@@ -52,7 +64,6 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r
# This test isn't valid if there are nodes to begin with
Puppet::Rails::InventoryNode.count.should == 0
- facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
Puppet::Node::Facts.indirection.save(facts)
Puppet::Rails::InventoryNode.count.should == 1
@@ -60,7 +71,6 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if => (Puppet.features.r
end
it "should save the facts" do
- facts = Puppet::Node::Facts.new("foo", "uptime_days" => "60", "kernel" => "Darwin")
Puppet::Node::Facts.indirection.save(facts)
Puppet::Rails::InventoryFact.all.map{|f| [f.name,f.value]}.should =~ [["uptime_days","60"],["kernel","Darwin"]]
diff --git a/spec/unit/indirector/instrumentation_data/local_spec.rb b/spec/unit/indirector/instrumentation_data/local_spec.rb
new file mode 100644
index 000000000..45ca1e07e
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_data/local_spec.rb
@@ -0,0 +1,52 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/listener'
+require 'puppet/indirector/instrumentation_data/local'
+
+describe Puppet::Indirector::InstrumentationData::Local do
+ it "should be a subclass of the Code terminus" do
+ Puppet::Indirector::InstrumentationData::Local.superclass.should equal(Puppet::Indirector::Code)
+ end
+
+ it "should be registered with the configuration store indirection" do
+ indirection = Puppet::Indirector::Indirection.instance(:instrumentation_data)
+ Puppet::Indirector::InstrumentationData::Local.indirection.should equal(indirection)
+ end
+
+ it "should have its name set to :local" do
+ Puppet::Indirector::InstrumentationData::Local.name.should == :local
+ end
+end
+
+describe Puppet::Indirector::InstrumentationData::Local do
+ before :each do
+ Puppet::Util::Instrumentation.stubs(:listener)
+ @data = Puppet::Indirector::InstrumentationData::Local.new
+ @name = "me"
+ @request = stub 'request', :key => @name
+ end
+
+ describe "when finding instrumentation data" do
+ it "should return a Instrumentation Data instance matching the key" do
+ end
+ end
+
+ describe "when searching listeners" do
+ it "should raise an error" do
+ lambda { @data.search(@request) }.should raise_error(Puppet::DevError)
+ end
+ end
+
+ describe "when saving listeners" do
+ it "should raise an error" do
+ lambda { @data.save(@request) }.should raise_error(Puppet::DevError)
+ end
+ end
+
+ describe "when destroying listeners" do
+ it "should raise an error" do
+ lambda { @data.destroy(@reques) }.should raise_error(Puppet::DevError)
+ end
+ end
+end
diff --git a/spec/unit/indirector/instrumentation_data/rest_spec.rb b/spec/unit/indirector/instrumentation_data/rest_spec.rb
new file mode 100644
index 000000000..762667ea7
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_data/rest_spec.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/data'
+require 'puppet/indirector/instrumentation_data/rest'
+
+describe Puppet::Indirector::InstrumentationData::Rest do
+ it "should be a subclass of Puppet::Indirector::REST" do
+ Puppet::Indirector::InstrumentationData::Rest.superclass.should equal(Puppet::Indirector::REST)
+ end
+end
diff --git a/spec/unit/indirector/instrumentation_listener/local_spec.rb b/spec/unit/indirector/instrumentation_listener/local_spec.rb
new file mode 100644
index 000000000..b251736b4
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_listener/local_spec.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/listener'
+require 'puppet/indirector/instrumentation_listener/local'
+
+describe Puppet::Indirector::InstrumentationListener::Local do
+ it "should be a subclass of the Code terminus" do
+ Puppet::Indirector::InstrumentationListener::Local.superclass.should equal(Puppet::Indirector::Code)
+ end
+
+ it "should be registered with the configuration store indirection" do
+ indirection = Puppet::Indirector::Indirection.instance(:instrumentation_listener)
+ Puppet::Indirector::InstrumentationListener::Local.indirection.should equal(indirection)
+ end
+
+ it "should have its name set to :local" do
+ Puppet::Indirector::InstrumentationListener::Local.name.should == :local
+ end
+end
+
+describe Puppet::Indirector::InstrumentationListener::Local do
+ before :each do
+ Puppet::Util::Instrumentation.stubs(:listener)
+ @listener = Puppet::Indirector::InstrumentationListener::Local.new
+ @name = "me"
+ @request = stub 'request', :key => @name
+ end
+
+ describe "when finding listeners" do
+ it "should return a Instrumentation Listener instance matching the key" do
+ Puppet::Util::Instrumentation.expects(:[]).with("me").returns(:instance)
+ @listener.find(@request).should == :instance
+ end
+ end
+
+ describe "when searching listeners" do
+ it "should return a list of all loaded Instrumentation Listenesrs irregardless of the given key" do
+ Puppet::Util::Instrumentation.expects(:listeners).returns([:instance1, :instance2])
+ @listener.search(@request).should == [:instance1, :instance2]
+ end
+ end
+
+ describe "when saving listeners" do
+ it "should set the new listener to the global listener list" do
+ newlistener = stub 'listener', :name => @name
+ @request.stubs(:instance).returns(newlistener)
+ Puppet::Util::Instrumentation.expects(:[]=).with("me", newlistener)
+ @listener.save(@request)
+ end
+ end
+
+ describe "when destroying listeners" do
+ it "should raise an error if listener wasn't subscribed" do
+ Puppet::Util::Instrumentation.expects(:[]).with("me").returns(nil)
+ lambda { @listener.destroy(@request) }.should raise_error
+ end
+
+ it "should unsubscribe the listener" do
+ Puppet::Util::Instrumentation.expects(:[]).with("me").returns(:instancce)
+ Puppet::Util::Instrumentation.expects(:unsubscribe).with(:instancce)
+ @listener.destroy(@request)
+ end
+ end
+end
diff --git a/spec/unit/indirector/instrumentation_listener/rest_spec.rb b/spec/unit/indirector/instrumentation_listener/rest_spec.rb
new file mode 100644
index 000000000..6355a1c53
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_listener/rest_spec.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/listener'
+require 'puppet/indirector/instrumentation_listener/rest'
+
+describe Puppet::Indirector::InstrumentationListener::Rest do
+ it "should be a subclass of Puppet::Indirector::REST" do
+ Puppet::Indirector::InstrumentationListener::Rest.superclass.should equal(Puppet::Indirector::REST)
+ end
+end
diff --git a/spec/unit/indirector/instrumentation_probe/local_spec.rb b/spec/unit/indirector/instrumentation_probe/local_spec.rb
new file mode 100644
index 000000000..40d64dc2b
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_probe/local_spec.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/indirection_probe'
+require 'puppet/indirector/instrumentation_probe/local'
+require 'puppet/util/instrumentation/instrumentable'
+
+describe Puppet::Indirector::InstrumentationProbe::Local do
+ it "should be a subclass of the Code terminus" do
+ Puppet::Indirector::InstrumentationProbe::Local.superclass.should equal(Puppet::Indirector::Code)
+ end
+
+ it "should be registered with the configuration store indirection" do
+ indirection = Puppet::Indirector::Indirection.instance(:instrumentation_probe)
+ Puppet::Indirector::InstrumentationProbe::Local.indirection.should equal(indirection)
+ end
+
+ it "should have its name set to :local" do
+ Puppet::Indirector::InstrumentationProbe::Local.name.should == :local
+ end
+end
+
+describe Puppet::Indirector::InstrumentationProbe::Local do
+ before :each do
+ Puppet::Util::Instrumentation.stubs(:listener)
+ @probe = Puppet::Indirector::InstrumentationProbe::Local.new
+ @name = "me"
+ @request = stub 'request', :key => @name
+ end
+
+ describe "when finding probes" do
+ it "should do nothing" do
+ @probe.find(@request).should be_nil
+ end
+ end
+
+ describe "when searching probes" do
+ it "should return a list of all loaded probes irregardless of the given key" do
+ instance1 = stub 'instance1', :method => "probe1", :klass => "Klass1"
+ instance2 = stub 'instance2', :method => "probe2", :klass => "Klass2"
+ Puppet::Util::Instrumentation::IndirectionProbe.expects(:new).with("Klass1.probe1").returns(:instance1)
+ Puppet::Util::Instrumentation::IndirectionProbe.expects(:new).with("Klass2.probe2").returns(:instance2)
+ Puppet::Util::Instrumentation::Instrumentable.expects(:each_probe).multiple_yields([instance1], [instance2])
+ @probe.search(@request).should == [ :instance1, :instance2 ]
+ end
+ end
+
+ describe "when saving probes" do
+ it "should enable probes" do
+ newprobe = stub 'probe', :name => @name
+ @request.stubs(:instance).returns(newprobe)
+ Puppet::Util::Instrumentation::Instrumentable.expects(:enable_probes)
+ @probe.save(@request)
+ end
+ end
+
+ describe "when destroying probes" do
+ it "should disable probes" do
+ newprobe = stub 'probe', :name => @name
+ @request.stubs(:instance).returns(newprobe)
+ Puppet::Util::Instrumentation::Instrumentable.expects(:disable_probes)
+ @probe.destroy(@request)
+ end
+ end
+end
diff --git a/spec/unit/indirector/instrumentation_probe/rest_spec.rb b/spec/unit/indirector/instrumentation_probe/rest_spec.rb
new file mode 100644
index 000000000..0b73fbdf5
--- /dev/null
+++ b/spec/unit/indirector/instrumentation_probe/rest_spec.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/instrumentation/indirection_probe'
+require 'puppet/indirector/instrumentation_probe/rest'
+
+describe Puppet::Indirector::InstrumentationProbe::Rest do
+ it "should be a subclass of Puppet::Indirector::REST" do
+ Puppet::Indirector::InstrumentationProbe::Rest.superclass.should equal(Puppet::Indirector::REST)
+ end
+end
diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb
index a0f64c6d3..e1172497d 100755
--- a/spec/unit/module_spec.rb
+++ b/spec/unit/module_spec.rb
@@ -89,83 +89,6 @@ describe Puppet::Module do
lambda { mod.validate_puppet_version }.should raise_error(Puppet::Module::IncompatibleModule)
end
- describe "when specifying required modules" do
- it "should support specifying a required module" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar"
- end
-
- it "should support specifying multiple required modules" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar"
- mod.requires "baz"
- end
-
- it "should support specifying a required module and version" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar", 1.0
- end
-
- it "should fail when required modules are missing" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar"
-
- mod.environment.expects(:module).with("foobar").returns nil
-
- lambda { mod.validate_dependencies }.should raise_error(Puppet::Module::MissingModule)
- end
-
- it "should fail when required modules are present but of the wrong version" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar", 1.0
-
- foobar = Puppet::Module.new("foobar")
- foobar.version = 2.0
-
- mod.environment.expects(:module).with("foobar").returns foobar
-
- lambda { mod.validate_dependencies }.should raise_error(Puppet::Module::IncompatibleModule)
- end
-
- it "should have valid dependencies when no dependencies have been specified" do
- mod = Puppet::Module.new("mymod")
-
- lambda { mod.validate_dependencies }.should_not raise_error
- end
-
- it "should fail when some dependencies are present but others aren't" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar"
- mod.requires "baz"
-
- mod.environment.expects(:module).with("foobar").returns Puppet::Module.new("foobar")
- mod.environment.expects(:module).with("baz").returns nil
-
- lambda { mod.validate_dependencies }.should raise_error(Puppet::Module::MissingModule)
- end
-
- it "should have valid dependencies when all dependencies are met" do
- mod = Puppet::Module.new("mymod")
- mod.requires "foobar", 1.0
- mod.requires "baz"
-
- foobar = Puppet::Module.new("foobar")
- foobar.version = 1.0
-
- baz = Puppet::Module.new("baz")
-
- mod.environment.expects(:module).with("foobar").returns foobar
- mod.environment.expects(:module).with("baz").returns baz
-
- lambda { mod.validate_dependencies }.should_not raise_error
- end
-
- it "should validate its dependendencies on initialization" do
- Puppet::Module.any_instance.expects(:validate_dependencies)
- Puppet::Module.new("mymod")
- end
- end
-
describe "when managing supported platforms" do
it "should support specifying a supported platform" do
mod = Puppet::Module.new("mymod")
@@ -251,11 +174,11 @@ describe Puppet::Module do
end
it "should convert an environment name into an Environment instance" do
- Puppet::Module.new("foo", "prod").environment.should be_instance_of(Puppet::Node::Environment)
+ Puppet::Module.new("foo", :environment => "prod").environment.should be_instance_of(Puppet::Node::Environment)
end
it "should accept an environment at initialization" do
- Puppet::Module.new("foo", :prod).environment.name.should == :prod
+ Puppet::Module.new("foo", :environment => :prod).environment.name.should == :prod
end
it "should use the default environment if none is provided" do
@@ -265,43 +188,53 @@ describe Puppet::Module do
it "should use any provided Environment instance" do
env = Puppet::Node::Environment.new
- Puppet::Module.new("foo", env).environment.should equal(env)
+ Puppet::Module.new("foo", :environment => env).environment.should equal(env)
end
- it "should return the path to the first found instance in its environment's module paths as its path" do
- dir = tmpdir("deep_path")
- first = File.join(dir, "first")
- second = File.join(dir, "second")
+ describe ".path" do
+ before do
+ dir = tmpdir("deep_path")
- FileUtils.mkdir_p(first)
- FileUtils.mkdir_p(second)
- Puppet[:modulepath] = "#{first}#{File::PATH_SEPARATOR}#{second}"
+ @first = File.join(dir, "first")
+ @second = File.join(dir, "second")
+ Puppet[:modulepath] = "#{@first}#{File::PATH_SEPARATOR}#{@second}"
- modpath = File.join(first, "foo")
- FileUtils.mkdir_p(modpath)
+ FileUtils.mkdir_p(@first)
+ FileUtils.mkdir_p(@second)
+ end
- # Make a second one, which we shouldn't find
- FileUtils.mkdir_p(File.join(second, "foo"))
+ it "should return the path to the first found instance in its environment's module paths as its path" do
+ modpath = File.join(@first, "foo")
+ FileUtils.mkdir_p(modpath)
- mod = Puppet::Module.new("foo")
- mod.path.should == modpath
- end
+ # Make a second one, which we shouldn't find
+ FileUtils.mkdir_p(File.join(@second, "foo"))
+
+ mod = Puppet::Module.new("foo")
+ mod.path.should == modpath
+ end
- it "should be able to find itself in a directory other than the first directory in the module path" do
- dir = tmpdir("deep_path")
- first = File.join(dir, "first")
- second = File.join(dir, "second")
+ it "should be able to find itself in a directory other than the first directory in the module path" do
+ modpath = File.join(@second, "foo")
+ FileUtils.mkdir_p(modpath)
- FileUtils.mkdir_p(first)
- FileUtils.mkdir_p(second)
- Puppet[:modulepath] = "#{first}#{File::PATH_SEPARATOR}#{second}"
+ mod = Puppet::Module.new("foo")
+ mod.should be_exist
+ mod.path.should == modpath
+ end
- modpath = File.join(second, "foo")
- FileUtils.mkdir_p(modpath)
+ it "should be able to find itself in a directory other than the first directory in the module path even when it exists in the first" do
+ environment = Puppet::Node::Environment.new
- mod = Puppet::Module.new("foo")
- mod.should be_exist
- mod.path.should == modpath
+ first_modpath = File.join(@first, "foo")
+ FileUtils.mkdir_p(first_modpath)
+ second_modpath = File.join(@second, "foo")
+ FileUtils.mkdir_p(second_modpath)
+
+ mod = Puppet::Module.new("foo", :environment => environment, :path => second_modpath)
+ mod.path.should == File.join(@second, "foo")
+ mod.environment.should == environment
+ end
end
it "should be considered existent if it exists in at least one module path" do
@@ -403,24 +336,6 @@ describe Puppet::Module do
end
end
-describe Puppet::Module, " when building its search path" do
- it "should use the current environment's search path if no environment is specified" do
- env = mock 'env'
- env.expects(:modulepath).returns "eh"
- Puppet::Node::Environment.expects(:new).with(nil).returns env
-
- Puppet::Module.modulepath.should == "eh"
- end
-
- it "should use the specified environment's search path if an environment is specified" do
- env = mock 'env'
- env.expects(:modulepath).returns "eh"
- Puppet::Node::Environment.expects(:new).with("foo").returns env
-
- Puppet::Module.modulepath("foo").should == "eh"
- end
-end
-
describe Puppet::Module, "when finding matching manifests" do
before do
@mod = Puppet::Module.new("mymod")
@@ -592,7 +507,6 @@ describe Puppet::Module do
@module.puppetversion.should == @data[:puppetversion]
end
-
it "should fail if the discovered name is different than the metadata name"
end
end
diff --git a/spec/unit/module_tool/application_spec.rb b/spec/unit/module_tool/application_spec.rb
new file mode 100644
index 000000000..22d3632fd
--- /dev/null
+++ b/spec/unit/module_tool/application_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+require 'puppet/module_tool'
+
+describe Puppet::Module::Tool::Applications::Application do
+ describe 'app' do
+
+ good_versions = %w{ 1.2.4 0.0.1 0.0.0 0.0.2git-8-g3d316d1 0.0.3b1 10.100.10000
+ 0.1.2rc1 0.1.2dev-1 0.1.2svn12345 }
+ bad_versions = %w{ 0.1.2-3 0.1 0 0.1.2.3 dev }
+
+ before do
+ @app = Class.new(described_class).new
+ end
+
+ good_versions.each do |ver|
+ it "should accept version string #{ver}" do
+ @app.instance_eval("@filename=%q{puppetlabs-ntp-#{ver}}")
+ @app.parse_filename!
+ end
+ end
+
+ bad_versions.each do |ver|
+ it "should not accept version string #{ver}" do
+ @app.instance_eval("@filename=%q{puppetlabs-ntp-#{ver}}")
+ lambda { @app.parse_filename! }.should raise_error
+ end
+ end
+ end
+end
diff --git a/spec/unit/module_tool/metadata_spec.rb b/spec/unit/module_tool/metadata_spec.rb
new file mode 100644
index 000000000..85d743fbc
--- /dev/null
+++ b/spec/unit/module_tool/metadata_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+require 'puppet/module_tool'
+
+describe Puppet::Module::Tool::Metadata do
+ context "when using default values" do
+ it "should set license to 'Apache License, Version 2.0'" do
+ metadata = Puppet::Module::Tool::Metadata.new
+ metadata.license.should == "Apache License, Version 2.0"
+ end
+ end
+end
diff --git a/spec/unit/module_tool/repository_spec.rb b/spec/unit/module_tool/repository_spec.rb
new file mode 100644
index 000000000..69be1661e
--- /dev/null
+++ b/spec/unit/module_tool/repository_spec.rb
@@ -0,0 +1,52 @@
+require 'spec_helper'
+require 'net/http'
+require 'puppet/module_tool'
+
+describe Puppet::Module::Tool::Repository do
+ describe 'instances' do
+ before do
+ @repository = described_class.new('http://fake.com')
+ end
+
+ describe '#make_http_request' do
+ before do
+ # Do a mock of the Proxy call so we can do proper expects for
+ # Net::HTTP
+ Net::HTTP.expects(:Proxy).returns(Net::HTTP)
+ Net::HTTP.expects(:start)
+ end
+ context "when not given an :authenticate option" do
+ it "should authenticate" do
+ @repository.expects(:authenticate).never
+ @repository.make_http_request(nil)
+ end
+ end
+ context "when given an :authenticate option" do
+ it "should authenticate" do
+ @repository.expects(:authenticate)
+ @repository.make_http_request(nil, :authenticate => true)
+ end
+ end
+ end
+
+ describe '#authenticate' do
+ it "should set basic auth on the request" do
+ authenticated_request = stub
+ authenticated_request.expects(:basic_auth)
+ @repository.expects(:prompt).twice
+ @repository.authenticate(authenticated_request)
+ end
+ end
+
+ describe '#retrieve' do
+ before do
+ @uri = URI.parse('http://some.url.com')
+ end
+
+ it "should access the cache" do
+ @repository.cache.expects(:retrieve).with(@uri)
+ @repository.retrieve(@uri)
+ end
+ end
+ end
+end
diff --git a/spec/unit/module_tool/uninstaller_spec.rb b/spec/unit/module_tool/uninstaller_spec.rb
new file mode 100644
index 000000000..abf2db0f8
--- /dev/null
+++ b/spec/unit/module_tool/uninstaller_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+require 'puppet/module_tool'
+require 'tmpdir'
+
+describe Puppet::Module::Tool::Applications::Uninstaller do
+ include PuppetSpec::Files
+
+ describe "instances" do
+ let(:tmp_module_path1) { tmpdir("uninstaller_module_path1") }
+ let(:tmp_module_path2) { tmpdir("uninstaller_module_path2") }
+ let(:options) do
+ { :target_directories => [ tmp_module_path1, tmp_module_path2 ] }
+ end
+
+ it "should return an empty list if the module is not installed" do
+ described_class.new('foo', options).run.should == []
+ end
+
+ it "should uninstall an installed module" do
+ foo_module_path = File.join(tmp_module_path1, 'foo')
+ Dir.mkdir(foo_module_path)
+ described_class.new('foo', options).run.should == [ foo_module_path ]
+ end
+
+ it "should only uninstall the requested module" do
+ foo_module_path = File.join(tmp_module_path1, 'foo')
+ bar_module_path = File.join(tmp_module_path1, 'bar')
+ Dir.mkdir(foo_module_path)
+ Dir.mkdir(bar_module_path)
+ described_class.new('foo', options).run.should == [ foo_module_path ]
+ end
+
+ it "should uninstall the module from all target directories" do
+ foo1_module_path = File.join(tmp_module_path1, 'foo')
+ foo2_module_path = File.join(tmp_module_path2, 'foo')
+ Dir.mkdir(foo1_module_path)
+ Dir.mkdir(foo2_module_path)
+ described_class.new('foo', options).run.should == [ foo1_module_path, foo2_module_path ]
+ end
+
+ #11803
+ it "should check for broken dependencies"
+ end
+end
diff --git a/spec/unit/module_tool_spec.rb b/spec/unit/module_tool_spec.rb
new file mode 100644
index 000000000..15ca6c766
--- /dev/null
+++ b/spec/unit/module_tool_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+require 'puppet/module_tool'
+
+describe Puppet::Module::Tool do
+ describe 'http_proxy support' do
+ before :each do
+ ENV["http_proxy"] = nil
+ end
+
+ after :each do
+ ENV["http_proxy"] = nil
+ end
+
+ it "should support environment variable for port and host" do
+ ENV["http_proxy"] = "http://test.com:8011"
+ described_class.http_proxy_host.should == "test.com"
+ described_class.http_proxy_port.should == 8011
+ end
+
+ it "should support puppet configuration for port and host" do
+ ENV["http_proxy"] = nil
+ Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test.com')
+ Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
+
+ described_class.http_proxy_port.should == 7456
+ described_class.http_proxy_host.should == "test.com"
+ end
+
+ it "should use environment variable before puppet settings" do
+ ENV["http_proxy"] = "http://test1.com:8011"
+ Puppet.settings.stubs(:[]).with(:http_proxy_host).returns('test2.com')
+ Puppet.settings.stubs(:[]).with(:http_proxy_port).returns(7456)
+
+ described_class.http_proxy_host.should == "test1.com"
+ described_class.http_proxy_port.should == 8011
+ end
+ end
+end
diff --git a/spec/unit/network/http/api/v1_spec.rb b/spec/unit/network/http/api/v1_spec.rb
index a952f24e2..039bccfd5 100755
--- a/spec/unit/network/http/api/v1_spec.rb
+++ b/spec/unit/network/http/api/v1_spec.rb
@@ -123,6 +123,10 @@ describe Puppet::Network::HTTP::API::V1 do
@tester.uri2indirection("GET", "/env/statuses/bar", {})[0].should == 'status'
end
+ it "should change indirection name to 'probe' if the http method is a GET and the indirection name is probes" do
+ @tester.uri2indirection("GET", "/env/probes/bar", {})[0].should == 'probe'
+ end
+
it "should choose 'delete' as the indirection method if the http method is a DELETE and the indirection name is singular" do
@tester.uri2indirection("DELETE", "/env/foo/bar", {})[1].should == :destroy
end
diff --git a/spec/unit/node/environment_spec.rb b/spec/unit/node/environment_spec.rb
index 78d383440..d5d3068a1 100755
--- a/spec/unit/node/environment_spec.rb
+++ b/spec/unit/node/environment_spec.rb
@@ -7,6 +7,8 @@ require 'puppet/node/environment'
require 'puppet/util/execution'
describe Puppet::Node::Environment do
+ let(:env) { Puppet::Node::Environment.new("testing") }
+
include PuppetSpec::Files
after do
Puppet::Node::Environment.clear
@@ -44,59 +46,57 @@ describe Puppet::Node::Environment do
describe "when managing known resource types" do
before do
- @env = Puppet::Node::Environment.new("dev")
- @collection = Puppet::Resource::TypeCollection.new(@env)
- @env.stubs(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
+ @collection = Puppet::Resource::TypeCollection.new(env)
+ env.stubs(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
Thread.current[:known_resource_types] = nil
end
it "should create a resource type collection if none exists" do
- Puppet::Resource::TypeCollection.expects(:new).with(@env).returns @collection
- @env.known_resource_types.should equal(@collection)
+ Puppet::Resource::TypeCollection.expects(:new).with(env).returns @collection
+ env.known_resource_types.should equal(@collection)
end
it "should reuse any existing resource type collection" do
- @env.known_resource_types.should equal(@env.known_resource_types)
+ env.known_resource_types.should equal(env.known_resource_types)
end
it "should perform the initial import when creating a new collection" do
- @env = Puppet::Node::Environment.new("dev")
- @env.expects(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
- @env.known_resource_types
+ env.expects(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
+ env.known_resource_types
end
it "should return the same collection even if stale if it's the same thread" do
Puppet::Resource::TypeCollection.stubs(:new).returns @collection
- @env.known_resource_types.stubs(:stale?).returns true
+ env.known_resource_types.stubs(:stale?).returns true
- @env.known_resource_types.should equal(@collection)
+ env.known_resource_types.should equal(@collection)
end
it "should return the current thread associated collection if there is one" do
Thread.current[:known_resource_types] = @collection
- @env.known_resource_types.should equal(@collection)
+ env.known_resource_types.should equal(@collection)
end
it "should give to all threads using the same environment the same collection if the collection isn't stale" do
- original_thread_type_collection = Puppet::Resource::TypeCollection.new(@env)
- Puppet::Resource::TypeCollection.expects(:new).with(@env).returns original_thread_type_collection
- @env.known_resource_types.should equal(original_thread_type_collection)
+ original_thread_type_collection = Puppet::Resource::TypeCollection.new(env)
+ Puppet::Resource::TypeCollection.expects(:new).with(env).returns original_thread_type_collection
+ env.known_resource_types.should equal(original_thread_type_collection)
original_thread_type_collection.expects(:require_reparse?).returns(false)
- Puppet::Resource::TypeCollection.stubs(:new).with(@env).returns @collection
+ Puppet::Resource::TypeCollection.stubs(:new).with(env).returns @collection
t = Thread.new {
- @env.known_resource_types.should equal(original_thread_type_collection)
+ env.known_resource_types.should equal(original_thread_type_collection)
}
t.join
end
it "should generate a new TypeCollection if the current one requires reparsing" do
- old_type_collection = @env.known_resource_types
+ old_type_collection = env.known_resource_types
old_type_collection.stubs(:require_reparse?).returns true
Thread.current[:known_resource_types] = nil
- new_type_collection = @env.known_resource_types
+ new_type_collection = env.known_resource_types
new_type_collection.should be_a Puppet::Resource::TypeCollection
new_type_collection.should_not equal(old_type_collection)
@@ -109,14 +109,11 @@ describe Puppet::Node::Environment do
Puppet[:modulepath] = path
- env = Puppet::Node::Environment.new("testing")
-
env.modulepath.should == [real_file]
end
it "should prefix the value of the 'PUPPETLIB' environment variable to the module path if present" do
Puppet::Util::Execution.withenv("PUPPETLIB" => %w{/l1 /l2}.join(File::PATH_SEPARATOR)) do
- env = Puppet::Node::Environment.new("testing")
module_path = %w{/one /two}.join(File::PATH_SEPARATOR)
env.expects(:validate_dirs).with(%w{/l1 /l2 /one /two}).returns %w{/l1 /l2 /one /two}
env.expects(:[]).with(:modulepath).returns module_path
@@ -132,8 +129,6 @@ describe Puppet::Node::Environment do
end
it "should not return non-directories" do
- env = Puppet::Node::Environment.new("testing")
-
FileTest.expects(:directory?).with(@path_one).returns true
FileTest.expects(:directory?).with(@path_two).returns false
@@ -142,7 +137,6 @@ describe Puppet::Node::Environment do
it "should use the current working directory to fully-qualify unqualified paths" do
FileTest.stubs(:directory?).returns true
- env = Puppet::Node::Environment.new("testing")
two = File.expand_path(File.join(Dir.getwd, "two"))
env.validate_dirs([@path_one, 'two']).should == [@path_one, two]
@@ -155,44 +149,75 @@ describe Puppet::Node::Environment do
end
it "should provide an array-like accessor method for returning any environment-specific setting" do
- env = Puppet::Node::Environment.new("testing")
env.should respond_to(:[])
end
it "should ask the Puppet settings instance for the setting qualified with the environment name" do
Puppet.settings.expects(:value).with("myvar", :testing).returns("myval")
- env = Puppet::Node::Environment.new("testing")
env["myvar"].should == "myval"
end
it "should be able to return an individual module that exists in its module path" do
- env = Puppet::Node::Environment.new("testing")
mod = mock 'module'
- Puppet::Module.expects(:new).with("one", env).returns mod
+ Puppet::Module.expects(:new).with("one", :environment => env).returns mod
mod.expects(:exist?).returns true
env.module("one").should equal(mod)
end
it "should return nil if asked for a module that does not exist in its path" do
- env = Puppet::Node::Environment.new("testing")
mod = mock 'module'
- Puppet::Module.expects(:new).with("one", env).returns mod
+ Puppet::Module.expects(:new).with("one", :environment => env).returns mod
mod.expects(:exist?).returns false
env.module("one").should be_nil
end
- it "should be able to return its modules" do
- Puppet::Node::Environment.new("testing").should respond_to(:modules)
+ describe ".modules_by_path" do
+ before do
+ dir = tmpdir("deep_path")
+
+ @first = File.join(dir, "first")
+ @second = File.join(dir, "second")
+ Puppet[:modulepath] = "#{@first}#{File::PATH_SEPARATOR}#{@second}"
+
+ FileUtils.mkdir_p(@first)
+ FileUtils.mkdir_p(@second)
+ end
+
+ it "should return an empty list if there are no modules" do
+ env.modules_by_path.should == {
+ @first => [],
+ @second => []
+ }
+ end
+
+ it "should include modules even if they exist in multiple dirs in the modulepath" do
+ modpath1 = File.join(@first, "foo")
+ FileUtils.mkdir_p(modpath1)
+ modpath2 = File.join(@second, "foo")
+ FileUtils.mkdir_p(modpath2)
+
+ env.modules_by_path.should == {
+ @first => [Puppet::Module.new('foo', :environment => env, :path => modpath1)],
+ @second => [Puppet::Module.new('foo', :environment => env, :path => modpath2)]
+ }
+ end
end
describe ".modules" do
+ it "should return an empty list if there are no modules" do
+ env.modulepath = %w{/a /b}
+ Dir.expects(:entries).with("/a").returns []
+ Dir.expects(:entries).with("/b").returns []
+
+ env.modules.should == []
+ end
+
it "should return a module named for every directory in each module path" do
- env = Puppet::Node::Environment.new("testing")
- env.expects(:modulepath).at_least_once.returns %w{/a /b}
+ env.modulepath = %w{/a /b}
Dir.expects(:entries).with("/a").returns %w{foo bar}
Dir.expects(:entries).with("/b").returns %w{bee baz}
@@ -200,8 +225,7 @@ describe Puppet::Node::Environment do
end
it "should remove duplicates" do
- env = Puppet::Node::Environment.new("testing")
- env.expects(:modulepath).returns( %w{/a /b} ).at_least_once
+ env.modulepath = %w{/a /b}
Dir.expects(:entries).with("/a").returns %w{foo}
Dir.expects(:entries).with("/b").returns %w{foo}
@@ -209,8 +233,7 @@ describe Puppet::Node::Environment do
end
it "should ignore invalid modules" do
- env = Puppet::Node::Environment.new("testing")
- env.stubs(:modulepath).returns %w{/a}
+ env.modulepath = %w{/a}
Dir.expects(:entries).with("/a").returns %w{foo bar}
Puppet::Module.expects(:new).with { |name, env| name == "foo" }.returns mock("foomod", :name => "foo")
@@ -220,16 +243,14 @@ describe Puppet::Node::Environment do
end
it "should create modules with the correct environment" do
- env = Puppet::Node::Environment.new("testing")
- env.expects(:modulepath).at_least_once.returns %w{/a}
+ env.modulepath = %w{/a}
Dir.expects(:entries).with("/a").returns %w{foo}
env.modules.each {|mod| mod.environment.should == env }
end
it "should cache the module list" do
- env = Puppet::Node::Environment.new("testing")
- env.expects(:modulepath).at_least_once.returns %w{/a}
+ env.modulepath = %w{/a}
Dir.expects(:entries).once.with("/a").returns %w{foo}
env.modules
@@ -244,20 +265,18 @@ describe Puppet::Node::Environment do
@helper.extend(Puppet::Node::Environment::Helper)
end
- it "should be able to set and retrieve the environment" do
+ it "should be able to set and retrieve the environment as a symbol" do
@helper.environment = :foo
@helper.environment.name.should == :foo
end
it "should accept an environment directly" do
- env = Puppet::Node::Environment.new :foo
- @helper.environment = env
+ @helper.environment = Puppet::Node::Environment.new(:foo)
@helper.environment.name.should == :foo
end
it "should accept an environment as a string" do
- env = Puppet::Node::Environment.new "foo"
- @helper.environment = env
+ @helper.environment = 'foo'
@helper.environment.name.should == :foo
end
end
@@ -266,14 +285,13 @@ describe Puppet::Node::Environment do
before do
@parser = Puppet::Parser::Parser.new("test")
Puppet::Parser::Parser.stubs(:new).returns @parser
- @env = Puppet::Node::Environment.new("env")
end
it "should set the parser's string to the 'code' setting and parse if code is available" do
Puppet.settings[:code] = "my code"
@parser.expects(:string=).with "my code"
@parser.expects(:parse)
- @env.instance_eval { perform_initial_import }
+ env.instance_eval { perform_initial_import }
end
it "should set the parser's file to the 'manifest' setting and parse if no code is available and the manifest is available" do
@@ -282,7 +300,7 @@ describe Puppet::Node::Environment do
Puppet.settings[:manifest] = filename
@parser.expects(:file=).with filename
@parser.expects(:parse)
- @env.instance_eval { perform_initial_import }
+ env.instance_eval { perform_initial_import }
end
it "should pass the manifest file to the parser even if it does not exist on disk" do
@@ -291,15 +309,15 @@ describe Puppet::Node::Environment do
Puppet.settings[:manifest] = filename
@parser.expects(:file=).with(filename).once
@parser.expects(:parse).once
- @env.instance_eval { perform_initial_import }
+ env.instance_eval { perform_initial_import }
end
it "should fail helpfully if there is an error importing" do
File.stubs(:exist?).returns true
- @env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(@env)
+ env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(env)
@parser.expects(:file=).once
@parser.expects(:parse).raises ArgumentError
- lambda { @env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error)
+ lambda { env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error)
end
it "should not do anything if the ignore_import settings is set" do
@@ -307,15 +325,15 @@ describe Puppet::Node::Environment do
@parser.expects(:string=).never
@parser.expects(:file=).never
@parser.expects(:parse).never
- @env.instance_eval { perform_initial_import }
+ env.instance_eval { perform_initial_import }
end
it "should mark the type collection as needing a reparse when there is an error parsing" do
@parser.expects(:parse).raises Puppet::ParseError.new("Syntax error at ...")
- @env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(@env)
+ env.stubs(:known_resource_types).returns Puppet::Resource::TypeCollection.new(env)
- lambda { @env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error, /Syntax error at .../)
- @env.known_resource_types.require_reparse?.should be_true
+ lambda { env.instance_eval { perform_initial_import } }.should raise_error(Puppet::Error, /Syntax error at .../)
+ env.known_resource_types.require_reparse?.should be_true
end
end
end
diff --git a/spec/unit/parser/ast/asthash_spec.rb b/spec/unit/parser/ast/asthash_spec.rb
index d7fbbfae9..ab1281f91 100755
--- a/spec/unit/parser/ast/asthash_spec.rb
+++ b/spec/unit/parser/ast/asthash_spec.rb
@@ -91,7 +91,6 @@ describe Puppet::Parser::AST::ASTHash do
it "should return a valid string with to_s" do
hash = Puppet::Parser::AST::ASTHash.new(:value => { "a" => "b", "c" => "d" })
-
- hash.to_s.should == '{a => b, c => d}'
+ ["{a => b, c => d}", "{c => d, a => b}"].should be_include hash.to_s
end
end
diff --git a/spec/unit/parser/ast/leaf_spec.rb b/spec/unit/parser/ast/leaf_spec.rb
index ff3fed5e9..881506ea4 100755
--- a/spec/unit/parser/ast/leaf_spec.rb
+++ b/spec/unit/parser/ast/leaf_spec.rb
@@ -151,6 +151,14 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
lambda { access.evaluate(@scope) }.should raise_error
end
+ it "should be able to return :undef for an unknown array index" do
+ @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns(["val1", "val2", "val3"])
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => 6 )
+
+ access.evaluate(@scope).should == :undef
+ end
+
it "should be able to return an hash value" do
@scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns({ "key1" => "val1", "key2" => "val2", "key3" => "val3" })
@@ -159,6 +167,14 @@ describe Puppet::Parser::AST::HashOrArrayAccess do
access.evaluate(@scope).should == "val2"
end
+ it "should be able to return :undef for unknown hash keys" do
+ @scope.stubs(:lookupvar).with { |name,options| name == 'a'}.returns({ "key1" => "val1", "key2" => "val2", "key3" => "val3" })
+
+ access = Puppet::Parser::AST::HashOrArrayAccess.new(:variable => "a", :key => "key12" )
+
+ access.evaluate(@scope).should == :undef
+ end
+
it "should be able to return an hash value with a numerical key" do
@scope.stubs(:lookupvar).with { |name,options| name == "a"}.returns({ "key1" => "val1", "key2" => "val2", "45" => "45", "key3" => "val3" })
diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb
index da76e75d0..64314f777 100755
--- a/spec/unit/parser/functions/create_resources_spec.rb
+++ b/spec/unit/parser/functions/create_resources_spec.rb
@@ -20,8 +20,9 @@ describe 'function for dynamically creating resources' do
it "should exist" do
Puppet::Parser::Functions.function(:create_resources).should == "function_create_resources"
end
- it 'should require two arguments' do
- lambda { @scope.function_create_resources(['foo']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2)')
+ it 'should require two or three arguments' do
+ lambda { @scope.function_create_resources(['foo']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (1; must be 2 or 3)')
+ lambda { @scope.function_create_resources(['foo', 'bar', 'blah', 'baz']) }.should raise_error(ArgumentError, 'create_resources(): wrong number of arguments (4; must be 2 or 3)')
end
describe 'when creating native types' do
before :each do
@@ -58,6 +59,11 @@ describe 'function for dynamically creating resources' do
foo.should be
rg.path_between(test,foo).should be
end
+ it 'should account for default values' do
+ @scope.function_create_resources(['file', {'/etc/foo'=>{'ensure'=>'present'}, '/etc/baz'=>{'group'=>'food'}}, {'group' => 'bar'}])
+ @compiler.catalog.resource(:file, "/etc/foo")['group'].should == 'bar'
+ @compiler.catalog.resource(:file, "/etc/baz")['group'].should == 'food'
+ end
end
describe 'when dynamically creating resource types' do
before :each do
@@ -103,6 +109,11 @@ notify{test:}
rg.path_between(test,blah).should be
@compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
end
+ it 'should account for default values' do
+ @scope.function_create_resources(['foo', {'blah'=>{}}, {'one' => 'two'}])
+ @scope.compiler.compile
+ @compiler.catalog.resource(:notify, "blah")['message'].should == 'two'
+ end
end
describe 'when creating classes' do
before :each do
@@ -114,7 +125,7 @@ notify{tester:}
@scope.resource=Puppet::Parser::Resource.new('class', 't', :scope => @scope)
Puppet::Parser::Functions.function(:create_resources)
end
- it 'should be able to create classes', :'fails_on_ruby_1.9.2' => true do
+ it 'should be able to create classes' do
@scope.function_create_resources(['class', {'bar'=>{'one'=>'two'}}])
@scope.compiler.compile
@compiler.catalog.resource(:notify, "test")['message'].should == 'two'
@@ -123,7 +134,7 @@ notify{tester:}
it 'should fail to create non-existing classes' do
lambda { @scope.function_create_resources(['class', {'blah'=>{'one'=>'two'}}]) }.should raise_error(ArgumentError ,'could not find hostclass blah')
end
- it 'should be able to add edges', :'fails_on_ruby_1.9.2' => true do
+ it 'should be able to add edges' do
@scope.function_create_resources(['class', {'bar'=>{'one'=>'two', 'require' => 'Notify[tester]'}}])
@scope.compiler.compile
rg = @scope.compiler.catalog.to_ral.relationship_graph
@@ -133,5 +144,11 @@ notify{tester:}
tester.should be
rg.path_between(tester,test).should be
end
+ it 'should account for default values' do
+ @scope.function_create_resources(['class', {'bar'=>{}}, {'one' => 'two'}])
+ @scope.compiler.compile
+ @compiler.catalog.resource(:notify, "test")['message'].should == 'two'
+ @compiler.catalog.resource(:class, "bar").should_not be_nil#['message'].should == 'two'
+ end
end
end
diff --git a/spec/unit/property/keyvalue_spec.rb b/spec/unit/property/keyvalue_spec.rb
index 821c61799..2bead50e3 100755
--- a/spec/unit/property/keyvalue_spec.rb
+++ b/spec/unit/property/keyvalue_spec.rb
@@ -35,8 +35,11 @@ describe klass do
@property.should_to_s({:foo => "baz", :bar => "boo"}) == "foo=baz;bar=boo"
end
- it "should return the passed in array values joined with the delimiter from is_to_s" do
- @property.is_to_s({"foo" => "baz" , "bar" => "boo"}).should == "foo=baz;bar=boo"
+ it "should return the passed in hash values joined with the delimiter from is_to_s" do
+ s = @property.is_to_s({"foo" => "baz" , "bar" => "boo"})
+
+ # We can't predict the order the hash is processed in...
+ ["foo=baz;bar=boo", "bar=boo;foo=baz"].should be_include s
end
describe "when calling inclusive?" do
diff --git a/spec/unit/provider/augeas/augeas_spec.rb b/spec/unit/provider/augeas/augeas_spec.rb
index 874f70a8d..52ebb34f9 100755
--- a/spec/unit/provider/augeas/augeas_spec.rb
+++ b/spec/unit/provider/augeas/augeas_spec.rb
@@ -353,7 +353,7 @@ describe provider_class do
@augeas_stub = stub("augeas")
@provider.aug = @augeas_stub
- @augeas_stub.stubs("get").with("/augeas/version").returns("0.7.2")
+ @augeas_stub.stubs("get").with("/augeas/version").returns("0.10.0")
@augeas_stub.stubs(:set).returns(true)
@augeas_stub.stubs(:save).returns(true)
end
@@ -467,7 +467,7 @@ describe provider_class do
@augeas = stub("augeas")
@provider.aug= @augeas
@provider.stubs(:get_augeas_version).returns("0.3.5")
- @augeas.stubs(:match).with("/augeas/events/saved")
+ @augeas.stubs(:match).with("/augeas/events/saved").returns([])
end
it "should handle set commands" do
diff --git a/spec/unit/provider/group/pw_spec.rb b/spec/unit/provider/group/pw_spec.rb
new file mode 100755
index 000000000..3dfc5ec71
--- /dev/null
+++ b/spec/unit/provider/group/pw_spec.rb
@@ -0,0 +1,81 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:group).provider(:pw)
+
+describe provider_class do
+ let :resource do
+ Puppet::Type.type(:group).new(:name => "testgroup", :provider => :pw)
+ end
+
+ let :provider do
+ resource.provider
+ end
+
+ describe "when creating groups" do
+ let :provider do
+ prov = resource.provider
+ prov.expects(:exists?).returns nil
+ prov
+ end
+
+ it "should run pw with no additional flags when no properties are given" do
+ provider.addcmd.must == [provider_class.command(:pw), "groupadd", "testgroup"]
+ provider.expects(:execute).with([provider_class.command(:pw), "groupadd", "testgroup"])
+ provider.create
+ end
+
+ it "should use -o when allowdupe is enabled" do
+ resource[:allowdupe] = true
+ provider.expects(:execute).with(includes("-o"))
+ provider.create
+ end
+
+ it "should use -g with the correct argument when the gid property is set" do
+ resource[:gid] = 12345
+ provider.expects(:execute).with(all_of(includes("-g"), includes(12345)))
+ provider.create
+ end
+
+ it "should use -M with the correct argument when the members property is set" do
+ resource[:members] = "user1"
+ provider.expects(:execute).with(all_of(includes("-M"), includes("user1")))
+ provider.create
+ end
+
+ it "should use -M with all the given users when the members property is set to an array" do
+ resource[:members] = ["user1", "user2"]
+ provider.expects(:execute).with(all_of(includes("-M"), includes("user1,user2")))
+ provider.create
+ end
+ end
+
+ describe "when deleting groups" do
+ it "should run pw with no additional flags" do
+ provider.expects(:exists?).returns true
+ provider.deletecmd.must == [provider_class.command(:pw), "groupdel", "testgroup"]
+ provider.expects(:execute).with([provider_class.command(:pw), "groupdel", "testgroup"])
+ provider.delete
+ end
+ end
+
+ describe "when modifying groups" do
+ it "should run pw with the correct arguments" do
+ provider.modifycmd("gid", 12345).must == [provider_class.command(:pw), "groupmod", "testgroup", "-g", 12345]
+ provider.expects(:execute).with([provider_class.command(:pw), "groupmod", "testgroup", "-g", 12345])
+ provider.gid = 12345
+ end
+
+ it "should use -M with the correct argument when the members property is changed" do
+ resource[:members] = "user1"
+ provider.expects(:execute).with(all_of(includes("-M"), includes("user2")))
+ provider.members = "user2"
+ end
+
+ it "should use -M with all the given users when the members property is changed with an array" do
+ resource[:members] = ["user1", "user2"]
+ provider.expects(:execute).with(all_of(includes("-M"), includes("user3,user4")))
+ provider.members = ["user3", "user4"]
+ end
+ end
+end
diff --git a/spec/unit/provider/nameservice/directoryservice_spec.rb b/spec/unit/provider/nameservice/directoryservice_spec.rb
index 7a83d7f20..c585b626f 100755
--- a/spec/unit/provider/nameservice/directoryservice_spec.rb
+++ b/spec/unit/provider/nameservice/directoryservice_spec.rb
@@ -95,3 +95,105 @@ describe 'DirectoryService.get_exec_preamble' do
Puppet::Provider::NameService::DirectoryService.get_exec_preamble('-list').should include("-plist")
end
end
+
+describe 'DirectoryService password behavior' do
+ # The below is a binary plist containing a ShadowHashData key which CONTAINS
+ # another binary plist. The nested binary plist contains a 'SALTED-SHA512'
+ # key that contains a base64 encoded salted-SHA512 password hash...
+ let (:binary_plist) { "bplist00\324\001\002\003\004\005\006\a\bXCRAM-MD5RNT]SALTED-SHA512[RECOVERABLEO\020 \231k2\3360\200GI\201\355J\216\202\215y\243\001\206J\300\363\032\031\022\006\2359\024\257\217<\361O\020\020F\353\at\377\277\226\276c\306\254\031\037J(\235O\020D\335\006{\3744g@\377z\204\322\r\332t\021\330\n\003\246K\223\356\034!P\261\305t\035\346\352p\206\003n\247MMA\310\301Z<\366\246\023\0161W3\340\357\000\317T\t\301\311+\204\246L7\276\370\320*\245O\021\002\000k\024\221\270x\353\001\237\346D}\377?\265]\356+\243\v[\350\316a\340h\376<\322\266\327\016\306n\272r\t\212A\253L\216\214\205\016\241 [\360/\335\002#\\A\372\241a\261\346\346\\\251\330\312\365\016\n\341\017\016\225&;\322\\\004*\ru\316\372\a \362?8\031\247\231\030\030\267\315\023\v\343{@\227\301s\372h\212\000a\244&\231\366\nt\277\2036,\027bZ+\223W\212g\333`\264\331N\306\307\362\257(^~ b\262\247&\231\261t\341\231%\244\247\203eOt\365\271\201\273\330\350\363C^A\327F\214!\217hgf\e\320k\260n\315u~\336\371M\t\235k\230S\375\311\303\240\351\037d\273\321y\335=K\016`_\317\230\2612_\023K\036\350\v\232\323Y\310\317_\035\227%\237\v\340\023\016\243\233\025\306:\227\351\370\364x\234\231\266\367\016w\275\333-\351\210}\375x\034\262\272kRuHa\362T/F!\347B\231O`K\304\037'k$$\245h)e\363\365mT\b\317\\2\361\026\351\254\375Jl1~\r\371\267\352\2322I\341\272\376\243^Un\266E7\230[VocUJ\220N\2116D/\025f=\213\314\325\vG}\311\360\377DT\307m\261&\263\340\272\243_\020\271rG^BW\210\030l\344\0324\335\233\300\023\272\225Im\330\n\227*Yv[\006\315\330y'\a\321\373\273A\240\305F{S\246I#/\355\2425\031\031GGF\270y\n\331\004\023G@\331\000\361\343\350\264$\032\355_\210y\000\205\342\375\212q\024\004\026W:\205 \363v?\035\270L-\270=\022\323\2003\v\336\277\t\237\356\374\n\267n\003\367\342\330;\371S\326\016`B6@Njm>\240\021%\336\345\002(P\204Yn\3279l\0228\264\254\304\2528t\372h\217\347sA\314\345\245\337)]\000\b\000\021\000\032\000\035\000+\0007\000Z\000m\000\264\000\000\000\000\000\000\002\001\000\000\000\000\000\000\000\t\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\270" }
+
+ # The below is a base64 encoded salted-SHA512 password hash.
+ let (:pw_string) { "\335\006{\3744g@\377z\204\322\r\332t\021\330\n\003\246K\223\356\034!P\261\305t\035\346\352p\206\003n\247MMA\310\301Z<\366\246\023\0161W3\340\357\000\317T\t\301\311+\204\246L7\276\370\320*\245" }
+
+ # The below is a salted-SHA512 password hash in hex.
+ let (:sha512_hash) { 'dd067bfc346740ff7a84d20dda7411d80a03a64b93ee1c2150b1c5741de6ea7086036ea74d4d41c8c15a3cf6a6130e315733e0ef00cf5409c1c92b84a64c37bef8d02aa5' }
+
+ let :plist_path do
+ '/var/db/dslocal/nodes/Default/users/jeff.plist'
+ end
+
+ let :ds_provider do
+ Puppet::Provider::NameService::DirectoryService
+ end
+
+ let :shadow_hash_data do
+ {'ShadowHashData' => [StringIO.new(binary_plist)]}
+ end
+
+ subject do
+ Puppet::Provider::NameService::DirectoryService
+ end
+
+ before :each do
+ subject.expects(:get_macosx_version_major).returns("10.7")
+ end
+
+ it 'should execute convert_binary_to_xml once when getting the password on >= 10.7' do
+ subject.expects(:convert_binary_to_xml).returns({'SALTED-SHA512' => StringIO.new(pw_string)})
+ File.expects(:exists?).with(plist_path).once.returns(true)
+ Plist.expects(:parse_xml).returns(shadow_hash_data)
+ # On Mac OS X 10.7 we first need to convert to xml when reading the password
+ subject.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout', plist_path)
+ subject.get_password('uid', 'jeff')
+ end
+
+ it 'should fail if a salted-SHA512 password hash is not passed in >= 10.7' do
+ expect {
+ subject.set_password('jeff', 'uid', 'badpassword')
+ }.should raise_error(RuntimeError, /OS X 10.7 requires a Salted SHA512 hash password of 136 characters./)
+ end
+
+ it 'should convert xml-to-binary and binary-to-xml when setting the pw on >= 10.7' do
+ subject.expects(:convert_binary_to_xml).returns({'SALTED-SHA512' => StringIO.new(pw_string)})
+ subject.expects(:convert_xml_to_binary).returns(binary_plist)
+ File.expects(:exists?).with(plist_path).once.returns(true)
+ Plist.expects(:parse_xml).returns(shadow_hash_data)
+ # On Mac OS X 10.7 we first need to convert to xml
+ subject.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout', plist_path)
+ # And again back to a binary plist or DirectoryService will complain
+ subject.expects(:plutil).with('-convert', 'binary1', plist_path)
+ Plist::Emit.expects(:save_plist).with(shadow_hash_data, plist_path)
+ subject.set_password('jeff', 'uid', sha512_hash)
+ end
+end
+
+describe '(#4855) directoryservice group resource failure' do
+ let :provider_class do
+ Puppet::Type.type(:group).provider(:directoryservice)
+ end
+
+ let :group_members do
+ ['root','jeff']
+ end
+
+ let :user_account do
+ ['root']
+ end
+
+ let :stub_resource do
+ stub('resource')
+ end
+
+ subject do
+ provider_class.new(stub_resource)
+ end
+
+ before :each do
+ @resource = stub("resource")
+ @provider = provider_class.new(@resource)
+ end
+
+ it 'should delete a group member if the user does not exist' do
+ stub_resource.stubs(:[]).with(:name).returns('fake_group')
+ stub_resource.stubs(:name).returns('fake_group')
+ subject.expects(:execute).with([:dseditgroup, '-o', 'edit', '-n', '.',
+ '-d', 'jeff',
+ 'fake_group']).raises(Puppet::ExecutionFailure,
+ 'it broke')
+ subject.expects(:execute).with([:dscl, '.', '-delete',
+ '/Groups/fake_group', 'GroupMembership',
+ 'jeff'])
+ subject.remove_unwanted_members(group_members, user_account)
+ end
+end
+
diff --git a/spec/unit/provider/package/pip_spec.rb b/spec/unit/provider/package/pip_spec.rb
index 97b3b5e73..7849ec49c 100755
--- a/spec/unit/provider/package/pip_spec.rb
+++ b/spec/unit/provider/package/pip_spec.rb
@@ -175,6 +175,13 @@ describe provider_class do
expect { @provider.method(:lazy_pip).call("freeze") }.to raise_error(NoMethodError)
end
+ it "should output a useful error message if pip is missing" do
+ @provider.expects(:pip).with('freeze').raises(NoMethodError)
+ @provider.expects(:which).with('pip').returns(nil)
+ expect { @provider.method(:lazy_pip).call("freeze") }.
+ to raise_error(NoMethodError, 'Could not locate the pip command.')
+ end
+
end
end
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
index 601c24009..5148ac079 100755
--- a/spec/unit/provider/package/yum_spec.rb
+++ b/spec/unit/provider/package/yum_spec.rb
@@ -30,16 +30,19 @@ describe provider do
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage')
@provider.install
end
+
it 'should use :install to update' do
@provider.expects(:install)
@provider.update
end
+
it 'should be able to set version' do
@resource.stubs(:should).with(:ensure).returns '1.2'
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :install, 'mypackage-1.2')
@provider.stubs(:query).returns :ensure => '1.2'
@provider.install
end
+
it 'should be able to downgrade' do
@resource.stubs(:should).with(:ensure).returns '1.0'
@provider.expects(:yum).with('-d', '0', '-e', '0', '-y', :downgrade, 'mypackage-1.0')
@@ -53,6 +56,7 @@ describe provider do
@provider.expects(:yum).with('-y', :erase, 'mypackage')
@provider.purge
end
+
it 'should use rpm to uninstall' do
@provider.expects(:rpm).with('-e', 'mypackage-1-1.i386')
@provider.uninstall
@@ -62,5 +66,45 @@ describe provider do
it 'should be versionable' do
provider.should be_versionable
end
-end
+ describe '#latest' do
+ describe 'when latest_info is nil' do
+ before :each do
+ @provider.stubs(:latest_info).returns(nil)
+ end
+
+ it 'raises if ensure is absent and latest_info is nil' do
+ @provider.stubs(:properties).returns({:ensure => :absent})
+
+ expect { @provider.latest }.to raise_error(
+ Puppet::DevError,
+ 'Tried to get latest on a missing package'
+ )
+ end
+
+ it 'returns the ensure value if the package is not already installed' do
+ @provider.stubs(:properties).returns({:ensure => '3.4.5'})
+
+ @provider.latest.should == '3.4.5'
+ end
+ end
+
+ describe 'when latest_info is populated' do
+ before :each do
+ @provider.stubs(:latest_info).returns({
+ :name => 'mypackage',
+ :epoch => '1',
+ :version => '2.3.4',
+ :release => '5',
+ :arch => 'i686',
+ :provider => :yum,
+ :ensure => '2.3.4-5'
+ })
+ end
+
+ it 'includes the epoch in the version string' do
+ @provider.latest.should == '1:2.3.4-5'
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/service/debian_spec.rb b/spec/unit/provider/service/debian_spec.rb
index 4e3d30d61..f858568dc 100755
--- a/spec/unit/provider/service/debian_spec.rb
+++ b/spec/unit/provider/service/debian_spec.rb
@@ -88,6 +88,21 @@ describe provider_class do
@provider.enabled?.should == :true
end
+ context "when invoke-rc.d exits with 105 status" do
+ it "links count is 4" do
+ @provider.stubs(:system)
+ $CHILD_STATUS.stubs(:exitstatus).returns(105)
+ @provider.stubs(:get_start_link_count).returns(4)
+ @provider.enabled?.should == :true
+ end
+ it "links count is less than 4" do
+ @provider.stubs(:system)
+ $CHILD_STATUS.stubs(:exitstatus).returns(105)
+ @provider.stubs(:get_start_link_count).returns(3)
+ @provider.enabled?.should == :false
+ end
+ end
+
# pick a range of non-[104.106] numbers, strings and booleans to test with.
[-100, -1, 0, 1, 100, "foo", "", :true, :false].each do |exitstatus|
it "should return false when invoke-rc.d exits with #{exitstatus} status" do
diff --git a/spec/unit/provider/service/launchd_spec.rb b/spec/unit/provider/service/launchd_spec.rb
index 04c1f466f..8651ac562 100755
--- a/spec/unit/provider/service/launchd_spec.rb
+++ b/spec/unit/provider/service/launchd_spec.rb
@@ -37,22 +37,21 @@ describe Puppet::Type.type(:service).provider(:launchd) do
describe "when checking whether the service is enabled on OS X 10.5" do
it "should return true in if the job plist says disabled is false" do
- Facter.stubs(:value).with(:macosx_productversion_major).returns('10.5')
- Facter.stubs(:value).with(:kernel).returns('Darwin')
- Facter.stubs(:value).with(:macaddress).returns('')
- Facter.stubs(:value).with(:arp).returns('')
+ subject.expects(:has_macosx_plist_overrides?).returns(false)
subject.expects(:plist_from_label).with(joblabel).returns(["foo", {"Disabled" => false}])
subject.expects(:resource).returns({:name => joblabel})
subject.enabled?.should == :true
end
it "should return true in if the job plist has no disabled key" do
+ subject.expects(:has_macosx_plist_overrides?).returns(false)
subject.expects(:resource).returns({:name => joblabel})
- subject.stubs(:plist_from_label).returns(["foo", {}])
+ subject.expects(:plist_from_label).returns(["foo", {}])
subject.enabled?.should == :true
end
it "should return false in if the job plist says disabled is true" do
+ subject.expects(:has_macosx_plist_overrides?).returns(false)
subject.expects(:resource).returns({:name => joblabel})
- subject.stubs(:plist_from_label).returns(["foo", {"Disabled" => true}])
+ subject.expects(:plist_from_label).returns(["foo", {"Disabled" => true}])
subject.enabled?.should == :false
end
end
@@ -61,7 +60,7 @@ describe Puppet::Type.type(:service).provider(:launchd) do
it "should return true if the job plist says disabled is true and the global overrides says disabled is false" do
provider.expects(:get_macosx_version_major).returns("10.6")
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => true}])
- provider.stubs(:read_plist).returns({joblabel => {"Disabled" => false}})
+ provider.expects(:read_plist).returns({joblabel => {"Disabled" => false}})
FileTest.expects(:file?).with(launchd_overrides).returns(true)
subject.stubs(:resource).returns({:name => joblabel})
subject.enabled?.should == :true
@@ -69,7 +68,7 @@ describe Puppet::Type.type(:service).provider(:launchd) do
it "should return false if the job plist says disabled is false and the global overrides says disabled is true" do
provider.expects(:get_macosx_version_major).returns("10.6")
subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}])
- provider.stubs(:read_plist).returns({joblabel => {"Disabled" => true}})
+ provider.expects(:read_plist).returns({joblabel => {"Disabled" => true}})
FileTest.expects(:file?).with(launchd_overrides).returns(true)
subject.stubs(:resource).returns({:name => joblabel})
subject.enabled?.should == :false
@@ -77,7 +76,7 @@ describe Puppet::Type.type(:service).provider(:launchd) do
it "should return true if the job plist and the global overrides have no disabled keys" do
provider.expects(:get_macosx_version_major).returns("10.6")
subject.expects(:plist_from_label).returns([joblabel, {}])
- provider.stubs(:read_plist).returns({})
+ provider.expects(:read_plist).returns({})
FileTest.expects(:file?).with(launchd_overrides).returns(true)
subject.stubs(:resource).returns({:name => joblabel})
subject.enabled?.should == :true
@@ -87,61 +86,69 @@ describe Puppet::Type.type(:service).provider(:launchd) do
describe "when starting the service" do
it "should look for the relevant plist once" do
subject.expects(:plist_from_label).returns([joblabel, {}]).once
- subject.stubs(:enabled?).returns :true
- subject.stubs(:execute).with([:launchctl, :load, joblabel])
+ subject.expects(:enabled?).returns :true
+ subject.expects(:execute).with([:launchctl, :load, joblabel])
subject.stubs(:resource).returns({:name => joblabel})
subject.start
end
it "should execute 'launchctl load' once without writing to the plist if the job is enabled" do
- subject.stubs(:plist_from_label).returns([joblabel, {}])
- subject.stubs(:enabled?).returns :true
+ subject.expects(:plist_from_label).returns([joblabel, {}])
+ subject.expects(:enabled?).returns :true
subject.expects(:execute).with([:launchctl, :load, joblabel]).once
subject.stubs(:resource).returns({:name => joblabel})
subject.start
end
it "should execute 'launchctl load' with writing to the plist once if the job is disabled" do
- subject.stubs(:plist_from_label).returns([joblabel, {}])
- subject.stubs(:enabled?).returns(:false)
+ subject.expects(:plist_from_label).returns([joblabel, {}])
+ subject.expects(:enabled?).returns(:false)
subject.stubs(:resource).returns({:name => joblabel})
subject.expects(:execute).with([:launchctl, :load, "-w", joblabel]).once
subject.start
end
it "should disable the job once if the job is disabled and should be disabled at boot" do
- subject.stubs(:plist_from_label).returns([joblabel, {"Disabled" => true}])
- subject.stubs(:enabled?).returns :false
- subject.stubs(:execute).with([:launchctl, :load, "-w", joblabel])
+ subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => true}])
+ subject.expects(:enabled?).returns :false
+ subject.expects(:execute).with([:launchctl, :load, "-w", joblabel])
subject.stubs(:resource).returns({:name => joblabel, :enable => :false})
subject.expects(:disable).once
subject.start
end
+ it "(#2773) should execute 'launchctl load -w' if the job is enabled but stopped" do
+ subject.expects(:plist_from_label).returns([joblabel, {}])
+ subject.expects(:enabled?).returns(:true)
+ subject.expects(:status).returns(:stopped)
+ subject.expects(:resource).returns({:name => joblabel}).twice
+ subject.expects(:execute).with([:launchctl, :load, '-w', joblabel])
+ subject.start
+ end
end
describe "when stopping the service" do
it "should look for the relevant plist once" do
subject.expects(:plist_from_label).returns([joblabel, {}]).once
- subject.stubs(:enabled?).returns :true
- subject.stubs(:execute).with([:launchctl, :unload, '-w', joblabel])
+ subject.expects(:enabled?).returns :true
+ subject.expects(:execute).with([:launchctl, :unload, '-w', joblabel])
subject.stubs(:resource).returns({:name => joblabel})
subject.stop
end
it "should execute 'launchctl unload' once without writing to the plist if the job is disabled" do
- subject.stubs(:plist_from_label).returns([joblabel, {}])
- subject.stubs(:enabled?).returns :false
+ subject.expects(:plist_from_label).returns([joblabel, {}])
+ subject.expects(:enabled?).returns :false
subject.expects(:execute).with([:launchctl, :unload, joblabel]).once
subject.stubs(:resource).returns({:name => joblabel})
subject.stop
end
it "should execute 'launchctl unload' with writing to the plist once if the job is enabled" do
- subject.stubs(:plist_from_label).returns([joblabel, {}])
- subject.stubs(:enabled?).returns :true
+ subject.expects(:plist_from_label).returns([joblabel, {}])
+ subject.expects(:enabled?).returns :true
subject.expects(:execute).with([:launchctl, :unload, '-w', joblabel]).once
subject.stubs(:resource).returns({:name => joblabel})
subject.stop
end
it "should enable the job once if the job is enabled and should be enabled at boot" do
- subject.stubs(:plist_from_label).returns([joblabel, {"Disabled" => false}])
- subject.stubs(:enabled?).returns :true
- subject.stubs(:execute).with([:launchctl, :unload, "-w", joblabel])
+ subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}])
+ subject.expects(:enabled?).returns :true
+ subject.expects(:execute).with([:launchctl, :unload, "-w", joblabel])
subject.stubs(:resource).returns({:name => joblabel, :enable => :true})
subject.expects(:enable).once
subject.stop
@@ -151,15 +158,15 @@ describe Puppet::Type.type(:service).provider(:launchd) do
describe "when enabling the service" do
it "should look for the relevant plist once" do ### Do we need this test? Differentiating it?
subject.expects(:plist_from_label).returns([joblabel, {}]).once
- subject.stubs(:enabled?).returns :false
- subject.stubs(:execute).with([:launchctl, :unload, joblabel])
+ subject.expects(:enabled?).returns :false
+ subject.expects(:execute).with([:launchctl, :unload, joblabel])
subject.stubs(:resource).returns({:name => joblabel, :enable => :true})
subject.stop
end
it "should check if the job is enabled once" do
- subject.stubs(:plist_from_label).returns([joblabel, {}]).once
+ subject.expects(:plist_from_label).returns([joblabel, {}]).once
subject.expects(:enabled?).once
- subject.stubs(:execute).with([:launchctl, :unload, joblabel])
+ subject.expects(:execute).with([:launchctl, :unload, joblabel])
subject.stubs(:resource).returns({:name => joblabel, :enable => :true})
subject.stop
end
@@ -168,8 +175,8 @@ describe Puppet::Type.type(:service).provider(:launchd) do
describe "when disabling the service" do
it "should look for the relevant plist once" do
subject.expects(:plist_from_label).returns([joblabel, {}]).once
- subject.stubs(:enabled?).returns :true
- subject.stubs(:execute).with([:launchctl, :unload, '-w', joblabel])
+ subject.expects(:enabled?).returns :true
+ subject.expects(:execute).with([:launchctl, :unload, '-w', joblabel])
subject.stubs(:resource).returns({:name => joblabel, :enable => :false})
subject.stop
end
@@ -177,8 +184,8 @@ describe Puppet::Type.type(:service).provider(:launchd) do
describe "when enabling the service on OS X 10.6" do
it "should write to the global launchd overrides file once" do
- provider.stubs(:get_macosx_version_major).returns("10.6")
- provider.stubs(:read_plist).returns({})
+ provider.expects(:get_macosx_version_major).returns("10.6")
+ provider.expects(:read_plist).returns({})
Plist::Emit.expects(:save_plist).once
subject.stubs(:resource).returns({:name => joblabel, :enable => :true})
subject.enable
@@ -200,15 +207,13 @@ describe Puppet::Type.type(:service).provider(:launchd) do
provider.instance_variable_set(:@macosx_version_major, nil)
end
it "should display a deprecation warning" do
- Facter.stubs(:value).with(:macosx_productversion_major).returns(nil)
- Facter.stubs(:value).with(:kernel).returns('Darwin')
- Facter.stubs(:value).with(:macosx_productversion).returns('10.5.8')
+ Facter.expects(:value).with(:macosx_productversion_major).returns(nil)
+ Facter.expects(:value).with(:macosx_productversion).returns('10.5.8')
+ Facter.expects(:loadfacts)
Puppet::Util::Warnings.expects(:maybe_log)
- provider.stubs(:read_plist).returns({joblabel => {"Disabled" => false}})
- subject.stubs(:plist_from_label).returns([joblabel, {"Disabled" => false}])
- subject.stubs(:enabled?).returns :false
- subject.stubs(:execute).with([:launchctl, :load, '-w', joblabel]).returns('')
- File.stubs(:open).returns('')
+ subject.expects(:plist_from_label).returns([joblabel, {"Disabled" => false}])
+ subject.expects(:enabled?).returns :false
+ File.expects(:open).returns('')
subject.stubs(:resource).returns({:name => joblabel, :enable => :true})
subject.enable
end
diff --git a/spec/unit/provider/service/smf_spec.rb b/spec/unit/provider/service/smf_spec.rb
index dc7438cae..752702940 100755
--- a/spec/unit/provider/service/smf_spec.rb
+++ b/spec/unit/provider/service/smf_spec.rb
@@ -92,7 +92,7 @@ describe provider_class do
it "should always execute external command 'svcadm enable /system/myservice'" do
@provider.stubs(:status).returns :running
- @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "/system/myservice"], true)
+ @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "-s", "/system/myservice"], true)
@provider.start
end
@@ -112,7 +112,7 @@ describe provider_class do
it "should import the manifest if service is missing" do
@provider.expects(:svccfg).with(:import, "/tmp/myservice.xml")
- @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "/system/myservice"], true)
+ @provider.expects(:texecute).with(:start, ["/usr/sbin/svcadm", :enable, "-s", "/system/myservice"], true)
@provider.expects(:svcs).with('-H', '-o', 'state,nstate', "/system/myservice").returns("online\t-")
@provider.start
end
@@ -125,7 +125,7 @@ describe provider_class do
describe "when stopping" do
it "should execute external command 'svcadm disable /system/myservice'" do
- @provider.expects(:texecute).with(:stop, ["/usr/sbin/svcadm", :disable, "/system/myservice"], true)
+ @provider.expects(:texecute).with(:stop, ["/usr/sbin/svcadm", :disable, "-s", "/system/myservice"], true)
@provider.stop
end
end
diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb
new file mode 100755
index 000000000..495fef35b
--- /dev/null
+++ b/spec/unit/provider/user/pw_spec.rb
@@ -0,0 +1,183 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:user).provider(:pw)
+
+describe provider_class do
+ let :resource do
+ Puppet::Type.type(:user).new(:name => "testuser", :provider => :pw)
+ end
+
+ describe "when creating users" do
+ let :provider do
+ prov = resource.provider
+ prov.expects(:exists?).returns nil
+ prov
+ end
+
+ it "should run pw with no additional flags when no properties are given" do
+ provider.addcmd.must == [provider_class.command(:pw), "useradd", "testuser"]
+ provider.expects(:execute).with([provider_class.command(:pw), "useradd", "testuser"])
+ provider.create
+ end
+
+ it "should use -o when allowdupe is enabled" do
+ resource[:allowdupe] = true
+ provider.expects(:execute).with(includes("-o"))
+ provider.create
+ end
+
+ it "should use -c with the correct argument when the comment property is set" do
+ resource[:comment] = "Testuser Name"
+ provider.expects(:execute).with(all_of(includes("-c"), includes("Testuser Name")))
+ provider.create
+ end
+
+ it "should use -e with the correct argument when the expiry property is set" do
+ resource[:expiry] = "2010-02-19"
+ provider.expects(:execute).with(all_of(includes("-e"), includes("19-02-2010")))
+ provider.create
+ end
+
+ it "should use -g with the correct argument when the gid property is set" do
+ resource[:gid] = 12345
+ provider.expects(:execute).with(all_of(includes("-g"), includes(12345)))
+ provider.create
+ end
+
+ it "should use -G with the correct argument when the groups property is set" do
+ resource[:groups] = "group1"
+ provider.expects(:execute).with(all_of(includes("-G"), includes("group1")))
+ provider.create
+ end
+
+ it "should use -G with all the given groups when the groups property is set to an array" do
+ resource[:groups] = ["group1", "group2"]
+ provider.expects(:execute).with(all_of(includes("-G"), includes("group1,group2")))
+ provider.create
+ end
+
+ it "should use -d with the correct argument when the home property is set" do
+ resource[:home] = "/home/testuser"
+ provider.expects(:execute).with(all_of(includes("-d"), includes("/home/testuser")))
+ provider.create
+ end
+
+ it "should use -m when the managehome property is enabled" do
+ resource[:managehome] = true
+ provider.expects(:execute).with(includes("-m"))
+ provider.create
+ end
+
+ it "should call the password set function with the correct argument when the password property is set" do
+ resource[:password] = "*"
+ provider.expects(:execute)
+ provider.expects(:password=).with("*")
+ provider.create
+ end
+
+ it "should use -s with the correct argument when the shell property is set" do
+ resource[:shell] = "/bin/sh"
+ provider.expects(:execute).with(all_of(includes("-s"), includes("/bin/sh")))
+ provider.create
+ end
+
+ it "should use -u with the correct argument when the uid property is set" do
+ resource[:uid] = 12345
+ provider.expects(:execute).with(all_of(includes("-u"), includes(12345)))
+ provider.create
+ end
+
+ # (#7500) -p should not be used to set a password (it means something else)
+ it "should not use -p when a password is given" do
+ resource[:password] = "*"
+ provider.addcmd.should_not include("-p")
+ provider.expects(:password=)
+ provider.expects(:execute).with(Not(includes("-p")))
+ provider.create
+ end
+ end
+
+ describe "when deleting users" do
+ it "should run pw with no additional flags" do
+ provider = resource.provider
+ provider.expects(:exists?).returns true
+ provider.deletecmd.must == [provider_class.command(:pw), "userdel", "testuser"]
+ provider.expects(:execute).with([provider_class.command(:pw), "userdel", "testuser"])
+ provider.delete
+ end
+ end
+
+ describe "when modifying users" do
+ let :provider do
+ resource.provider
+ end
+
+ it "should run pw with the correct arguments" do
+ provider.modifycmd("uid", 12345).must == [provider_class.command(:pw), "usermod", "testuser", "-u", 12345]
+ provider.expects(:execute).with([provider_class.command(:pw), "usermod", "testuser", "-u", 12345])
+ provider.uid = 12345
+ end
+
+ it "should use -c with the correct argument when the comment property is changed" do
+ resource[:comment] = "Testuser Name"
+ provider.expects(:execute).with(all_of(includes("-c"), includes("Testuser New Name")))
+ provider.comment = "Testuser New Name"
+ end
+
+ it "should use -e with the correct argument when the expiry property is changed" do
+ resource[:expiry] = "2010-02-19"
+ provider.expects(:execute).with(all_of(includes("-e"), includes("19-02-2011")))
+ provider.expiry = "2011-02-19"
+ end
+
+ it "should use -g with the correct argument when the gid property is changed" do
+ resource[:gid] = 12345
+ provider.expects(:execute).with(all_of(includes("-g"), includes(54321)))
+ provider.gid = 54321
+ end
+
+ it "should use -G with the correct argument when the groups property is changed" do
+ resource[:groups] = "group1"
+ provider.expects(:execute).with(all_of(includes("-G"), includes("group2")))
+ provider.groups = "group2"
+ end
+
+ it "should use -G with all the given groups when the groups property is changed with an array" do
+ resource[:groups] = ["group1", "group2"]
+ provider.expects(:execute).with(all_of(includes("-G"), includes("group3,group4")))
+ provider.groups = "group3,group4"
+ end
+
+ it "should use -d with the correct argument when the home property is changed" do
+ resource[:home] = "/home/testuser"
+ provider.expects(:execute).with(all_of(includes("-d"), includes("/newhome/testuser")))
+ provider.home = "/newhome/testuser"
+ end
+
+ it "should use -m and -d with the correct argument when the home property is changed and managehome is enabled" do
+ resource[:home] = "/home/testuser"
+ resource[:managehome] = true
+ provider.expects(:execute).with(all_of(includes("-d"), includes("/newhome/testuser"), includes("-m")))
+ provider.home = "/newhome/testuser"
+ end
+
+ it "should call the password set function with the correct argument when the password property is changed" do
+ resource[:password] = "*"
+ provider.expects(:password=).with("!")
+ provider.password = "!"
+ end
+
+ it "should use -s with the correct argument when the shell property is changed" do
+ resource[:shell] = "/bin/sh"
+ provider.expects(:execute).with(all_of(includes("-s"), includes("/bin/tcsh")))
+ provider.shell = "/bin/tcsh"
+ end
+
+ it "should use -u with the correct argument when the uid property is changed" do
+ resource[:uid] = 12345
+ provider.expects(:execute).with(all_of(includes("-u"), includes(54321)))
+ provider.uid = 54321
+ end
+ end
+end
diff --git a/spec/unit/provider/user/windows_adsi_spec.rb b/spec/unit/provider/user/windows_adsi_spec.rb
index 6eff947e0..23fba9983 100755
--- a/spec/unit/provider/user/windows_adsi_spec.rb
+++ b/spec/unit/provider/user/windows_adsi_spec.rb
@@ -74,6 +74,7 @@ describe Puppet::Type.type(:user).provider(:windows_adsi) do
user.stubs(:groups).returns(['group2', 'group3'])
create = sequence('create')
+ user.expects(:password=).in_sequence(create)
user.expects(:commit).in_sequence(create)
user.expects(:set_groups).with('group1,group2', false).in_sequence(create)
user.expects(:[]=).with('Description', 'a test user')
diff --git a/spec/unit/rails_spec.rb b/spec/unit/rails_spec.rb
index fe7fd8e29..60062db1c 100755
--- a/spec/unit/rails_spec.rb
+++ b/spec/unit/rails_spec.rb
@@ -88,169 +88,100 @@ describe Puppet::Rails, "when initializing a sqlite3 connection", :if => Puppet.
end
end
-describe Puppet::Rails, "when initializing a mysql connection", :if => Puppet.features.rails? do
- it "should provide the adapter, log_level, and host, port, username, password, database, and reconnect arguments" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 45).to_s)
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("")
-
- Puppet::Rails.database_arguments.should == {
- :adapter => "mysql",
- :log_level => "testlevel",
- :host => "testserver",
- :username => "testuser",
- :password => "testpassword",
- :pool => pool_size,
- :database => "testname",
- :reconnect => true
- }
- end
-
- it "should provide the adapter, log_level, and host, port, username, password, database, socket, connections, and reconnect arguments" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 12).to_s)
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
-
- Puppet::Rails.database_arguments.should == {
- :adapter => "mysql",
- :log_level => "testlevel",
- :host => "testserver",
- :port => "9999",
- :username => "testuser",
- :password => "testpassword",
- :pool => pool_size,
- :database => "testname",
- :socket => "testsocket",
- :reconnect => true
- }
- end
-
- it "should provide the adapter, log_level, and host, port, username, password, database, socket, and connections arguments" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 23).to_s)
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
-
- Puppet::Rails.database_arguments.should == {
- :adapter => "mysql",
- :log_level => "testlevel",
- :host => "testserver",
- :port => "9999",
- :username => "testuser",
- :password => "testpassword",
- :pool => pool_size,
- :database => "testname",
- :socket => "testsocket",
- :reconnect => true
- }
- end
-
- it "should not provide the pool if dbconnections is 0, '0', or ''" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
-
- Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
- Puppet::Rails.database_arguments.should_not be_include(:pool)
-
- Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
- Puppet::Rails.database_arguments.should_not be_include(:pool)
-
- Puppet.settings.stubs(:value).with(:dbconnections).returns('')
- Puppet::Rails.database_arguments.should_not be_include(:pool)
- end
-end
-
-describe Puppet::Rails, "when initializing a postgresql connection", :if => Puppet.features.rails? do
- it "should provide the adapter, log_level, and host, port, username, password, connections, and database arguments" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("postgresql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 200).to_s)
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("")
-
- Puppet::Rails.database_arguments.should == {
- :adapter => "postgresql",
- :log_level => "testlevel",
- :host => "testserver",
- :port => "9999",
- :username => "testuser",
- :password => "testpassword",
- :pool => pool_size,
- :database => "testname",
- :reconnect => true
- }
- end
+['mysql','mysql2','postgresql'].each do |dbadapter|
+ describe Puppet::Rails, "when initializing a #{dbadapter} connection", :if => Puppet.features.rails? do
+ it "should provide the adapter, log_level, and host, port, username, password, database, and reconnect arguments" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns(dbadapter)
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 45).to_s)
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("")
+
+ Puppet::Rails.database_arguments.should == {
+ :adapter => dbadapter,
+ :log_level => "testlevel",
+ :host => "testserver",
+ :username => "testuser",
+ :password => "testpassword",
+ :pool => pool_size,
+ :database => "testname",
+ :reconnect => true
+ }
+ end
- it "should provide the adapter, log_level, and host, port, username, password, database, connections, and socket arguments" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("postgresql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 122).to_s)
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+ it "should provide the adapter, log_level, and host, port, username, password, database, socket, connections, and reconnect arguments" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns(dbadapter)
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 12).to_s)
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+
+ Puppet::Rails.database_arguments.should == {
+ :adapter => dbadapter,
+ :log_level => "testlevel",
+ :host => "testserver",
+ :port => "9999",
+ :username => "testuser",
+ :password => "testpassword",
+ :pool => pool_size,
+ :database => "testname",
+ :socket => "testsocket",
+ :reconnect => true
+ }
+ end
- Puppet::Rails.database_arguments.should == {
- :adapter => "postgresql",
- :log_level => "testlevel",
- :host => "testserver",
- :port => "9999",
- :username => "testuser",
- :password => "testpassword",
- :pool => pool_size,
- :database => "testname",
- :socket => "testsocket",
- :reconnect => true
- }
- end
+ it "should provide the adapter, log_level, and host, port, username, password, database, socket, and connections arguments" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns(dbadapter)
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbconnections).returns((pool_size = 23).to_s)
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+
+ Puppet::Rails.database_arguments.should == {
+ :adapter => dbadapter,
+ :log_level => "testlevel",
+ :host => "testserver",
+ :port => "9999",
+ :username => "testuser",
+ :password => "testpassword",
+ :pool => pool_size,
+ :database => "testname",
+ :socket => "testsocket",
+ :reconnect => true
+ }
+ end
- it "should not provide the pool if dbconnections is 0, '0', or ''" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
- Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
- Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
- Puppet.settings.stubs(:value).with(:dbport).returns("9999")
- Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
- Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
- Puppet.settings.stubs(:value).with(:dbname).returns("testname")
- Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
+ it "should not provide the pool if dbconnections is 0, '0', or ''" do
+ Puppet.settings.stubs(:value).with(:dbadapter).returns(dbadapter)
+ Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
+ Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
+ Puppet.settings.stubs(:value).with(:dbport).returns("9999")
+ Puppet.settings.stubs(:value).with(:dbuser).returns("testuser")
+ Puppet.settings.stubs(:value).with(:dbpassword).returns("testpassword")
+ Puppet.settings.stubs(:value).with(:dbname).returns("testname")
+ Puppet.settings.stubs(:value).with(:dbsocket).returns("testsocket")
- Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
- Puppet::Rails.database_arguments.should_not be_include(:pool)
+ Puppet.settings.stubs(:value).with(:dbconnections).returns(0)
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
- Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
- Puppet::Rails.database_arguments.should_not be_include(:pool)
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('0')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
- Puppet.settings.stubs(:value).with(:dbconnections).returns('')
- Puppet::Rails.database_arguments.should_not be_include(:pool)
+ Puppet.settings.stubs(:value).with(:dbconnections).returns('')
+ Puppet::Rails.database_arguments.should_not be_include(:pool)
+ end
end
end
@@ -292,7 +223,7 @@ describe Puppet::Rails, "when initializing an Oracle connection", :if => Puppet.
end
it "should not provide the pool if dbconnections is 0, '0', or ''" do
- Puppet.settings.stubs(:value).with(:dbadapter).returns("mysql")
+ Puppet.settings.stubs(:value).with(:dbadapter).returns("oracle_enhanced")
Puppet.settings.stubs(:value).with(:rails_loglevel).returns("testlevel")
Puppet.settings.stubs(:value).with(:dbserver).returns("testserver")
Puppet.settings.stubs(:value).with(:dbport).returns("9999")
diff --git a/spec/unit/reports/store_spec.rb b/spec/unit/reports/store_spec.rb
index 73a7e353f..5b752c4b7 100755
--- a/spec/unit/reports/store_spec.rb
+++ b/spec/unit/reports/store_spec.rb
@@ -3,6 +3,9 @@ require 'spec_helper'
require 'puppet/reports'
require 'time'
+require 'pathname'
+require 'tempfile'
+require 'fileutils'
processor = Puppet::Reports.report(:store)
@@ -10,7 +13,7 @@ describe processor do
describe "#process" do
include PuppetSpec::Files
before :each do
- Puppet[:reportdir] = tmpdir('reports') << '/reports'
+ Puppet[:reportdir] = File.join(tmpdir('reports'), 'reports')
@report = YAML.load_file(File.join(PuppetSpec::FIXTURE_DIR, 'yaml/report2.6.x.yaml')).extend processor
end
@@ -26,5 +29,20 @@ describe processor do
File.read(File.join(Puppet[:reportdir], @report.host, "201101061200.yaml")).should == @report.to_yaml
end
+
+ it "should write to the report directory in the correct sequence" do
+ # By doing things in this sequence we should protect against race
+ # conditions
+ Time.stubs(:now).returns(Time.parse("2011-01-06 12:00:00 UTC"))
+ writeseq = sequence("write")
+ file = mock "file"
+ Tempfile.expects(:new).in_sequence(writeseq).returns(file)
+ file.expects(:chmod).in_sequence(writeseq).with(0640)
+ file.expects(:print).with(@report.to_yaml).in_sequence(writeseq)
+ file.expects(:close).in_sequence(writeseq)
+ file.stubs(:path).returns(File.join(Dir.tmpdir, "foo123"))
+ FileUtils.expects(:mv).in_sequence(writeseq).with(File.join(Dir.tmpdir, "foo123"), File.join(Puppet[:reportdir], @report.host, "201101061200.yaml"))
+ @report.process
+ end
end
end
diff --git a/spec/unit/ssl/certificate_factory_spec.rb b/spec/unit/ssl/certificate_factory_spec.rb
index fc1b3a740..88521b0fb 100755
--- a/spec/unit/ssl/certificate_factory_spec.rb
+++ b/spec/unit/ssl/certificate_factory_spec.rb
@@ -52,19 +52,19 @@ describe Puppet::SSL::CertificateFactory do
it "should have 24 hours grace on the start of the cert" do
cert = subject.build(:server, csr, issuer, serial)
- cert.not_before.should be_within(1).of(Time.now - 24*60*60)
+ cert.not_before.should be_within(30).of(Time.now - 24*60*60)
end
it "should set the default TTL of the certificate" do
ttl = Puppet::SSL::CertificateFactory.ttl
cert = subject.build(:server, csr, issuer, serial)
- cert.not_after.should be_within(1).of(Time.now + ttl)
+ cert.not_after.should be_within(30).of(Time.now + ttl)
end
it "should respect a custom TTL for the CA" do
Puppet[:ca_ttl] = 12
cert = subject.build(:server, csr, issuer, serial)
- cert.not_after.should be_within(1).of(Time.now + 12)
+ cert.not_after.should be_within(30).of(Time.now + 12)
end
it "should build extensions for the certificate" do
diff --git a/spec/unit/ssl/host_spec.rb b/spec/unit/ssl/host_spec.rb
index dd6434359..3f94407be 100755
--- a/spec/unit/ssl/host_spec.rb
+++ b/spec/unit/ssl/host_spec.rb
@@ -182,57 +182,48 @@ describe Puppet::SSL::Host do
it "should cache the localhost instance" do
host = stub 'host', :certificate => "eh", :key => 'foo'
Puppet::SSL::Host.expects(:new).once.returns host
-
Puppet::SSL::Host.localhost.should == Puppet::SSL::Host.localhost
end
it "should be able to verify its certificate matches its key" do
- Puppet::SSL::Host.new("foo").should respond_to(:certificate_matches_key?)
+ Puppet::SSL::Host.new("foo").should respond_to(:validate_certificate_with_key)
end
it "should consider the certificate invalid if it cannot find a key" do
host = Puppet::SSL::Host.new("foo")
+ certificate = mock('cert', :fingerprint => 'DEADBEEF')
+ host.expects(:certificate).twice.returns certificate
host.expects(:key).returns nil
-
- host.should_not be_certificate_matches_key
+ lambda { host.validate_certificate_with_key }.should raise_error(Puppet::Error, "No private key with which to validate certificate with fingerprint: DEADBEEF")
end
it "should consider the certificate invalid if it cannot find a certificate" do
host = Puppet::SSL::Host.new("foo")
- host.expects(:key).returns mock("key")
+ host.expects(:key).never
host.expects(:certificate).returns nil
-
- host.should_not be_certificate_matches_key
+ lambda { host.validate_certificate_with_key }.should raise_error(Puppet::Error, "No certificate to validate.")
end
it "should consider the certificate invalid if the SSL certificate's key verification fails" do
host = Puppet::SSL::Host.new("foo")
-
key = mock 'key', :content => "private_key"
sslcert = mock 'sslcert'
- certificate = mock 'cert', :content => sslcert
-
+ certificate = mock 'cert', {:content => sslcert, :fingerprint => 'DEADBEEF'}
host.stubs(:key).returns key
host.stubs(:certificate).returns certificate
-
sslcert.expects(:check_private_key).with("private_key").returns false
-
- host.should_not be_certificate_matches_key
+ lambda { host.validate_certificate_with_key }.should raise_error(Puppet::Error, /DEADBEEF/)
end
it "should consider the certificate valid if the SSL certificate's key verification succeeds" do
host = Puppet::SSL::Host.new("foo")
-
key = mock 'key', :content => "private_key"
sslcert = mock 'sslcert'
certificate = mock 'cert', :content => sslcert
-
host.stubs(:key).returns key
host.stubs(:certificate).returns certificate
-
sslcert.expects(:check_private_key).with("private_key").returns true
-
- host.should be_certificate_matches_key
+ lambda{ host.validate_certificate_with_key }.should_not raise_error
end
describe "when specifying the CA location" do
@@ -511,15 +502,13 @@ describe Puppet::SSL::Host do
before do
@realcert = mock 'certificate'
@cert = stub 'cert', :content => @realcert
-
@host.stubs(:key).returns mock("key")
- @host.stubs(:certificate_matches_key?).returns true
+ @host.stubs(:validate_certificate_with_key)
end
it "should find the CA certificate if it does not have a certificate" do
Puppet::SSL::Certificate.indirection.expects(:find).with(Puppet::SSL::CA_NAME).returns mock("cacert")
Puppet::SSL::Certificate.indirection.stubs(:find).with("myname").returns @cert
-
@host.certificate
end
@@ -541,34 +530,22 @@ describe Puppet::SSL::Host do
it "should find the key if it does not have one" do
Puppet::SSL::Certificate.indirection.stubs(:find)
@host.expects(:key).returns mock("key")
-
@host.certificate
end
it "should generate the key if one cannot be found" do
Puppet::SSL::Certificate.indirection.stubs(:find)
-
@host.expects(:key).returns nil
@host.expects(:generate_key)
-
@host.certificate
end
it "should find the certificate in the Certificate class and return the Puppet certificate instance" do
Puppet::SSL::Certificate.indirection.expects(:find).with(Puppet::SSL::CA_NAME).returns mock("cacert")
Puppet::SSL::Certificate.indirection.expects(:find).with("myname").returns @cert
-
@host.certificate.should equal(@cert)
end
- it "should fail if the found certificate does not match the private key" do
- @host.expects(:certificate_matches_key?).returns false
-
- Puppet::SSL::Certificate.indirection.stubs(:find).returns @cert
-
- lambda { @host.certificate }.should raise_error(Puppet::Error)
- end
-
it "should return any previously found certificate" do
Puppet::SSL::Certificate.indirection.expects(:find).with(Puppet::SSL::CA_NAME).returns mock("cacert")
Puppet::SSL::Certificate.indirection.expects(:find).with("myname").returns(@cert).once
diff --git a/spec/unit/transaction/report_spec.rb b/spec/unit/transaction/report_spec.rb
index fe5c2e218..91a294d01 100755
--- a/spec/unit/transaction/report_spec.rb
+++ b/spec/unit/transaction/report_spec.rb
@@ -179,6 +179,11 @@ describe Puppet::Transaction::Report do
@report.finalize_report
metric(:resources, state.to_s).should == 3
end
+
+ it "should provide 0 for states not in status" do
+ @report.finalize_report
+ metric(:resources, state.to_s).should == 0
+ end
end
it "should mark the report as 'failed' if there are failing resources" do
@@ -274,13 +279,14 @@ describe Puppet::Transaction::Report do
resource = Puppet::Type.type(:notify).new(:name => "testing")
catalog = Puppet::Resource::Catalog.new
catalog.add_resource resource
+ catalog.version = 1234567
trans = catalog.apply
@report = trans.report
@report.finalize_report
end
- %w{changes time resources events}.each do |main|
+ %w{changes time resources events version}.each do |main|
it "should include the key #{main} in the raw summary hash" do
@report.raw_summary.should be_key main
end
@@ -291,6 +297,28 @@ describe Puppet::Transaction::Report do
@report.raw_summary["time"]["last_run"].should == 1289390424
end
+ it "should include all resource statuses" do
+ resources_report = @report.raw_summary["resources"]
+ Puppet::Resource::Status::STATES.each do |state|
+ resources_report.should be_include(state.to_s)
+ end
+ end
+
+ %w{total failure success}.each do |r|
+ it "should include event #{r}" do
+ events_report = @report.raw_summary["events"]
+ events_report.should be_include(r)
+ end
+ end
+
+ it "should include config version" do
+ @report.raw_summary["version"]["config"].should == 1234567
+ end
+
+ it "should include puppet version" do
+ @report.raw_summary["version"]["puppet"].should == Puppet.version
+ end
+
%w{Changes Total Resources Time Events}.each do |main|
it "should include information on #{main} in the textual summary" do
@report.summary.should be_include(main)
diff --git a/spec/unit/transaction_spec.rb b/spec/unit/transaction_spec.rb
index 9e85390eb..f5720e75a 100755
--- a/spec/unit/transaction_spec.rb
+++ b/spec/unit/transaction_spec.rb
@@ -436,6 +436,10 @@ describe Puppet::Transaction do
@transaction.catalog.add_resource(dependent, dependent2)
+ # We enqueue them here just so we can check their blockers. This is done
+ # again in traverse.
+ graph.enqueue_roots
+
graph.blockers[dependent].should == 1
graph.blockers[dependent2].should == 1
@@ -453,6 +457,8 @@ describe Puppet::Transaction do
@transaction.catalog.add_resource(dependent, dependent2)
+ graph.enqueue_roots
+
graph.blockers[dependent].should == 1
graph.blockers[dependent2].should == 1
@@ -510,70 +516,50 @@ describe Puppet::Transaction do
end
end
- describe "when generating resources" do
- it "should call 'generate' on all created resources" do
- first = Puppet::Type.type(:notify).new(:name => "first")
- second = Puppet::Type.type(:notify).new(:name => "second")
- third = Puppet::Type.type(:notify).new(:name => "third")
+ describe "when generating resources before traversal" do
+ let(:catalog) { Puppet::Resource::Catalog.new }
+ let(:transaction) { Puppet::Transaction.new(catalog) }
+ let(:generator) { Puppet::Type.type(:notify).create :title => "generator" }
+ let(:generated) do
+ %w[a b c].map { |name| Puppet::Type.type(:notify).new(:name => name) }
+ end
- @catalog = Puppet::Resource::Catalog.new
- @transaction = Puppet::Transaction.new(@catalog)
+ before :each do
+ catalog.add_resource generator
+ generator.stubs(:generate).returns generated
+ end
- first.expects(:generate).returns [second]
- second.expects(:generate).returns [third]
- third.expects(:generate)
+ it "should call 'generate' on all created resources" do
+ generated.each { |res| res.expects(:generate) }
- @transaction.generate_additional_resources(first)
+ transaction.add_dynamically_generated_resources
end
it "should finish all resources" do
- generator = stub 'generator', :depthfirst? => true, :tags => [], :ref => "Some[resource]"
- resource = stub 'resource', :tag => nil
-
- @catalog = Puppet::Resource::Catalog.new
- @transaction = Puppet::Transaction.new(@catalog)
-
- generator.expects(:generate).returns [resource]
-
- @catalog.expects(:add_resource).yields(resource)
-
- resource.expects(:finish)
+ generated.each { |res| res.expects(:finish) }
- @transaction.generate_additional_resources(generator)
+ transaction.add_dynamically_generated_resources
end
it "should skip generated resources that conflict with existing resources" do
- generator = mock 'generator', :tags => []
- resource = stub 'resource', :tag => nil
-
- @catalog = Puppet::Resource::Catalog.new
- @transaction = Puppet::Transaction.new(@catalog)
+ duplicate = generated.first
+ catalog.add_resource(duplicate)
- generator.expects(:generate).returns [resource]
+ duplicate.expects(:finish).never
- @catalog.expects(:add_resource).raises(Puppet::Resource::Catalog::DuplicateResourceError.new("foo"))
+ duplicate.expects(:info).with { |msg| msg =~ /Duplicate generated resource/ }
- resource.expects(:finish).never
- resource.expects(:info) # log that it's skipped
-
- @transaction.generate_additional_resources(generator)
+ transaction.add_dynamically_generated_resources
end
it "should copy all tags to the newly generated resources" do
- child = stub 'child', :ref => "Some[child_resource]"
- generator = stub 'resource', :tags => ["one", "two"], :ref => "Some[resource]"
-
- @catalog = Puppet::Resource::Catalog.new
- @transaction = Puppet::Transaction.new(@catalog)
-
- generator.stubs(:generate).returns [child]
- @catalog.stubs(:add_resource)
+ generator.tag('one', 'two')
- child.expects(:tag).with("one", "two")
- child.expects(:finish)
- generator.expects(:depthfirst?)
+ transaction.add_dynamically_generated_resources
- @transaction.generate_additional_resources(generator)
+ generated.each do |res|
+ res.should be_tagged(generator.tags)
+ end
end
end
diff --git a/spec/unit/type/file/mode_spec.rb b/spec/unit/type/file/mode_spec.rb
index 2c6772aba..88881043c 100755
--- a/spec/unit/type/file/mode_spec.rb
+++ b/spec/unit/type/file/mode_spec.rb
@@ -21,7 +21,7 @@ describe Puppet::Type.type(:file).attrclass(:mode) do
it "should not accept strings other than octal numbers" do
expect do
mode.value = 'readable please!'
- end.to raise_error(Puppet::Error, /File modes can only be octal numbers/)
+ end.to raise_error(Puppet::Error, /The file mode specification is invalid/)
end
end
diff --git a/spec/unit/type/file/source_spec.rb b/spec/unit/type/file/source_spec.rb
index f77645770..50e3679ef 100755
--- a/spec/unit/type/file/source_spec.rb
+++ b/spec/unit/type/file/source_spec.rb
@@ -156,8 +156,10 @@ describe Puppet::Type.type(:file).attrclass(:source) do
@resource = Puppet::Type.type(:file).new :path => @foobar
@source = source.new(:resource => @resource)
- @metadata = stub 'metadata', :owner => 100, :group => 200, :mode => 123, :checksum => "{md5}asdfasdf", :ftype => "file"
+ @metadata = stub 'metadata', :owner => 100, :group => 200, :mode => 123, :checksum => "{md5}asdfasdf", :ftype => "file", :source => @foobar
@source.stubs(:metadata).returns @metadata
+
+ Puppet.features.stubs(:root?).returns true
end
it "should fail if there is no metadata" do
@@ -184,11 +186,10 @@ describe Puppet::Type.type(:file).attrclass(:source) do
describe "and the source is a file" do
before do
@metadata.stubs(:ftype).returns "file"
+ Puppet.features.stubs(:microsoft_windows?).returns false
end
it "should copy the metadata's owner, group, checksum, and mode to the resource if they are not set on the resource" do
- Puppet.features.expects(:root?).returns true
-
@source.copy_source_values
@resource[:owner].must == 100
@@ -221,6 +222,30 @@ describe Puppet::Type.type(:file).attrclass(:source) do
@resource[:owner].should be_nil
end
end
+
+ describe "on Windows" do
+ before :each do
+ Puppet.features.stubs(:microsoft_windows?).returns true
+ end
+
+ it "should not copy owner and group from remote sources" do
+ @source.stubs(:local?).returns false
+
+ @source.copy_source_values
+
+ @resource[:owner].must be_nil
+ @resource[:group].must be_nil
+ end
+
+ it "should copy owner and group from local sources" do
+ @source.stubs(:local?).returns true
+
+ @source.copy_source_values
+
+ @resource[:owner].must == 100
+ @resource[:group].must == 200
+ end
+ end
end
describe "and the source is a link" do
diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb
index cf278b4f8..d4df006b3 100755
--- a/spec/unit/type/file_spec.rb
+++ b/spec/unit/type/file_spec.rb
@@ -500,8 +500,9 @@ describe Puppet::Type.type(:file) do
end
it "should not copy values to the child which were set by the source" do
- file[:source] = File.expand_path(__FILE__)
- metadata = stub 'metadata', :owner => "root", :group => "root", :mode => 0755, :ftype => "file", :checksum => "{md5}whatever"
+ source = File.expand_path(__FILE__)
+ file[:source] = source
+ metadata = stub 'metadata', :owner => "root", :group => "root", :mode => 0755, :ftype => "file", :checksum => "{md5}whatever", :source => source
file.parameter(:source).stubs(:metadata).returns metadata
file.parameter(:source).copy_source_values
@@ -841,7 +842,7 @@ describe Puppet::Type.type(:file) do
describe "and multiple sources are provided" do
let(:sources) do
h = {}
- %w{/one /two /three /four}.each do |key|
+ %w{/a /b /c /d}.each do |key|
h[key] = URI.unescape(Puppet::Util.path_to_uri(File.expand_path(key)).to_s)
end
h
@@ -850,11 +851,11 @@ describe Puppet::Type.type(:file) do
describe "and :sourceselect is set to :first" do
it "should create file instances for the results for the first source to return any values" do
data = Puppet::FileServing::Metadata.new("/whatever", :relative_path => "foobar")
- file[:source] = sources.keys.map { |key| File.expand_path(key) }
- file.expects(:perform_recursion).with(sources['/one']).returns nil
- file.expects(:perform_recursion).with(sources['/two']).returns []
- file.expects(:perform_recursion).with(sources['/three']).returns [data]
- file.expects(:perform_recursion).with(sources['/four']).never
+ file[:source] = sources.keys.sort.map { |key| File.expand_path(key) }
+ file.expects(:perform_recursion).with(sources['/a']).returns nil
+ file.expects(:perform_recursion).with(sources['/b']).returns []
+ file.expects(:perform_recursion).with(sources['/c']).returns [data]
+ file.expects(:perform_recursion).with(sources['/d']).never
file.expects(:newchild).with("foobar").returns @resource
file.recurse_remote({})
end
@@ -867,22 +868,22 @@ describe Puppet::Type.type(:file) do
it "should return every found file that is not in a previous source" do
klass = Puppet::FileServing::Metadata
- file[:source] = %w{/one /two /three /four}.map {|f| File.expand_path(f) }
+ file[:source] = %w{/a /b /c /d}.map {|f| File.expand_path(f) }
file.stubs(:newchild).returns @resource
- one = [klass.new("/one", :relative_path => "a")]
- file.expects(:perform_recursion).with(sources['/one']).returns one
+ one = [klass.new("/a", :relative_path => "a")]
+ file.expects(:perform_recursion).with(sources['/a']).returns one
file.expects(:newchild).with("a").returns @resource
- two = [klass.new("/two", :relative_path => "a"), klass.new("/two", :relative_path => "b")]
- file.expects(:perform_recursion).with(sources['/two']).returns two
+ two = [klass.new("/b", :relative_path => "a"), klass.new("/b", :relative_path => "b")]
+ file.expects(:perform_recursion).with(sources['/b']).returns two
file.expects(:newchild).with("b").returns @resource
- three = [klass.new("/three", :relative_path => "a"), klass.new("/three", :relative_path => "c")]
- file.expects(:perform_recursion).with(sources['/three']).returns three
+ three = [klass.new("/c", :relative_path => "a"), klass.new("/c", :relative_path => "c")]
+ file.expects(:perform_recursion).with(sources['/c']).returns three
file.expects(:newchild).with("c").returns @resource
- file.expects(:perform_recursion).with(sources['/four']).returns []
+ file.expects(:perform_recursion).with(sources['/d']).returns []
file.recurse_remote({})
end
@@ -1253,6 +1254,36 @@ describe Puppet::Type.type(:file) do
end
describe "when autorequiring" do
+ describe "target" do
+ it "should require file resource when specified with the target property" do
+ file = described_class.new(:path => File.expand_path("/foo"), :ensure => :directory)
+ link = described_class.new(:path => File.expand_path("/bar"), :ensure => :symlink, :target => File.expand_path("/foo"))
+ catalog.add_resource file
+ catalog.add_resource link
+ reqs = link.autorequire
+ reqs.size.must == 1
+ reqs[0].source.must == file
+ reqs[0].target.must == link
+ end
+
+ it "should require file resource when specified with the ensure property" do
+ file = described_class.new(:path => File.expand_path("/foo"), :ensure => :directory)
+ link = described_class.new(:path => File.expand_path("/bar"), :ensure => File.expand_path("/foo"))
+ catalog.add_resource file
+ catalog.add_resource link
+ reqs = link.autorequire
+ reqs.size.must == 1
+ reqs[0].source.must == file
+ reqs[0].target.must == link
+ end
+
+ it "should not require target if target is not managed" do
+ link = described_class.new(:path => File.expand_path('/foo'), :ensure => :symlink, :target => '/bar')
+ catalog.add_resource link
+ link.autorequire.size.should == 0
+ end
+ end
+
describe "directories" do
it "should autorequire its parent directory" do
dir = described_class.new(:path => File.dirname(path))
diff --git a/spec/unit/type/host_spec.rb b/spec/unit/type/host_spec.rb
index 602c428af..3cbe56943 100755
--- a/spec/unit/type/host_spec.rb
+++ b/spec/unit/type/host_spec.rb
@@ -70,10 +70,537 @@ describe host do
proc { @class.new(:name => "foo", :ip => '192.168.0.300') }.should raise_error
end
+ it "should reject over-long IPv4 addresses" do
+ expect { @class.new(:name => "foo", :ip => '10.10.10.10.10') }.to raise_error
+ end
+
it "should not accept malformed IP addresses like 2001:0dg8:85a3:08d3:1319:8a2e:0370:7344" do
proc { @class.new(:name => "foo", :ip => '2001:0dg8:85a3:08d3:1319:8a2e:0370:7344') }.should raise_error
end
+ # Assorted, annotated IPv6 passes.
+ ["::1", # loopback, compressed, non-routable
+ "::", # unspecified, compressed, non-routable
+ "0:0:0:0:0:0:0:1", # loopback, full
+ "0:0:0:0:0:0:0:0", # unspecified, full
+ "2001:DB8:0:0:8:800:200C:417A", # unicast, full
+ "FF01:0:0:0:0:0:0:101", # multicast, full
+ "2001:DB8::8:800:200C:417A", # unicast, compressed
+ "FF01::101", # multicast, compressed
+ # Some more test cases that should pass.
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876",
+ "3ffe:0b00:0000:0000:0001:0000:0000:000a",
+ "FF02:0000:0000:0000:0000:0000:0000:0001",
+ "0000:0000:0000:0000:0000:0000:0000:0001",
+ "0000:0000:0000:0000:0000:0000:0000:0000",
+ # Assorted valid, compressed IPv6 addresses.
+ "2::10",
+ "ff02::1",
+ "fe80::",
+ "2002::",
+ "2001:db8::",
+ "2001:0db8:1234::",
+ "::ffff:0:0",
+ "::1",
+ "1:2:3:4:5:6:7:8",
+ "1:2:3:4:5:6::8",
+ "1:2:3:4:5::8",
+ "1:2:3:4::8",
+ "1:2:3::8",
+ "1:2::8",
+ "1::8",
+ "1::2:3:4:5:6:7",
+ "1::2:3:4:5:6",
+ "1::2:3:4:5",
+ "1::2:3:4",
+ "1::2:3",
+ "1::8",
+ "::2:3:4:5:6:7:8",
+ "::2:3:4:5:6:7",
+ "::2:3:4:5:6",
+ "::2:3:4:5",
+ "::2:3:4",
+ "::2:3",
+ "::8",
+ "1:2:3:4:5:6::",
+ "1:2:3:4:5::",
+ "1:2:3:4::",
+ "1:2:3::",
+ "1:2::",
+ "1::",
+ "1:2:3:4:5::7:8",
+ "1:2:3:4::7:8",
+ "1:2:3::7:8",
+ "1:2::7:8",
+ "1::7:8",
+ # IPv4 addresses as dotted-quads
+ "1:2:3:4:5:6:1.2.3.4",
+ "1:2:3:4:5::1.2.3.4",
+ "1:2:3:4::1.2.3.4",
+ "1:2:3::1.2.3.4",
+ "1:2::1.2.3.4",
+ "1::1.2.3.4",
+ "1:2:3:4::5:1.2.3.4",
+ "1:2:3::5:1.2.3.4",
+ "1:2::5:1.2.3.4",
+ "1::5:1.2.3.4",
+ "1::5:11.22.33.44",
+ "fe80::217:f2ff:254.7.237.98",
+ "::ffff:192.168.1.26",
+ "::ffff:192.168.1.1",
+ "0:0:0:0:0:0:13.1.68.3", # IPv4-compatible IPv6 address, full, deprecated
+ "0:0:0:0:0:FFFF:129.144.52.38", # IPv4-mapped IPv6 address, full
+ "::13.1.68.3", # IPv4-compatible IPv6 address, compressed, deprecated
+ "::FFFF:129.144.52.38", # IPv4-mapped IPv6 address, compressed
+ "fe80:0:0:0:204:61ff:254.157.241.86",
+ "fe80::204:61ff:254.157.241.86",
+ "::ffff:12.34.56.78",
+ "::ffff:192.0.2.128", # this is OK, since there's a single zero digit in IPv4
+ "fe80:0000:0000:0000:0204:61ff:fe9d:f156",
+ "fe80:0:0:0:204:61ff:fe9d:f156",
+ "fe80::204:61ff:fe9d:f156",
+ "::1",
+ "fe80::",
+ "fe80::1",
+ "::ffff:c000:280",
+
+ # Additional test cases from http://rt.cpan.org/Public/Bug/Display.html?id=50693
+ "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+ "2001:db8:85a3:0:0:8a2e:370:7334",
+ "2001:db8:85a3::8a2e:370:7334",
+ "2001:0db8:0000:0000:0000:0000:1428:57ab",
+ "2001:0db8:0000:0000:0000::1428:57ab",
+ "2001:0db8:0:0:0:0:1428:57ab",
+ "2001:0db8:0:0::1428:57ab",
+ "2001:0db8::1428:57ab",
+ "2001:db8::1428:57ab",
+ "0000:0000:0000:0000:0000:0000:0000:0001",
+ "::1",
+ "::ffff:0c22:384e",
+ "2001:0db8:1234:0000:0000:0000:0000:0000",
+ "2001:0db8:1234:ffff:ffff:ffff:ffff:ffff",
+ "2001:db8:a::123",
+ "fe80::",
+
+ "1111:2222:3333:4444:5555:6666:7777:8888",
+ "1111:2222:3333:4444:5555:6666:7777::",
+ "1111:2222:3333:4444:5555:6666::",
+ "1111:2222:3333:4444:5555::",
+ "1111:2222:3333:4444::",
+ "1111:2222:3333::",
+ "1111:2222::",
+ "1111::",
+ "1111:2222:3333:4444:5555:6666::8888",
+ "1111:2222:3333:4444:5555::8888",
+ "1111:2222:3333:4444::8888",
+ "1111:2222:3333::8888",
+ "1111:2222::8888",
+ "1111::8888",
+ "::8888",
+ "1111:2222:3333:4444:5555::7777:8888",
+ "1111:2222:3333:4444::7777:8888",
+ "1111:2222:3333::7777:8888",
+ "1111:2222::7777:8888",
+ "1111::7777:8888",
+ "::7777:8888",
+ "1111:2222:3333:4444::6666:7777:8888",
+ "1111:2222:3333::6666:7777:8888",
+ "1111:2222::6666:7777:8888",
+ "1111::6666:7777:8888",
+ "::6666:7777:8888",
+ "1111:2222:3333::5555:6666:7777:8888",
+ "1111:2222::5555:6666:7777:8888",
+ "1111::5555:6666:7777:8888",
+ "::5555:6666:7777:8888",
+ "1111:2222::4444:5555:6666:7777:8888",
+ "1111::4444:5555:6666:7777:8888",
+ "::4444:5555:6666:7777:8888",
+ "1111::3333:4444:5555:6666:7777:8888",
+ "::3333:4444:5555:6666:7777:8888",
+ "::2222:3333:4444:5555:6666:7777:8888",
+ "1111:2222:3333:4444:5555:6666:123.123.123.123",
+ "1111:2222:3333:4444:5555::123.123.123.123",
+ "1111:2222:3333:4444::123.123.123.123",
+ "1111:2222:3333::123.123.123.123",
+ "1111:2222::123.123.123.123",
+ "1111::123.123.123.123",
+ "::123.123.123.123",
+ "1111:2222:3333:4444::6666:123.123.123.123",
+ "1111:2222:3333::6666:123.123.123.123",
+ "1111:2222::6666:123.123.123.123",
+ "1111::6666:123.123.123.123",
+ "::6666:123.123.123.123",
+ "1111:2222:3333::5555:6666:123.123.123.123",
+ "1111:2222::5555:6666:123.123.123.123",
+ "1111::5555:6666:123.123.123.123",
+ "::5555:6666:123.123.123.123",
+ "1111:2222::4444:5555:6666:123.123.123.123",
+ "1111::4444:5555:6666:123.123.123.123",
+ "::4444:5555:6666:123.123.123.123",
+ "1111::3333:4444:5555:6666:123.123.123.123",
+ "::2222:3333:4444:5555:6666:123.123.123.123",
+
+ # Playing with combinations of "0" and "::"; these are all sytactically
+ # correct, but are bad form because "0" adjacent to "::" should be
+ # combined into "::"
+ "::0:0:0:0:0:0:0",
+ "::0:0:0:0:0:0",
+ "::0:0:0:0:0",
+ "::0:0:0:0",
+ "::0:0:0",
+ "::0:0",
+ "::0",
+ "0:0:0:0:0:0:0::",
+ "0:0:0:0:0:0::",
+ "0:0:0:0:0::",
+ "0:0:0:0::",
+ "0:0:0::",
+ "0:0::",
+ "0::",
+
+ # Additional cases: http://crisp.tweakblogs.net/blog/2031/ipv6-validation-%28and-caveats%29.html
+ "0:a:b:c:d:e:f::",
+ "::0:a:b:c:d:e:f", # syntactically correct, but bad form (::0:... could be combined)
+ "a:b:c:d:e:f:0::",
+ ].each do |ip|
+ it "should accept #{ip.inspect} as an IPv6 address" do
+ expect { @class.new(:name => "foo", :ip => ip) }.not_to raise_error
+ end
+ end
+
+ # ...aaaand, some failure cases.
+ [":",
+ "02001:0000:1234:0000:0000:C1C0:ABCD:0876", # extra 0 not allowed!
+ "2001:0000:1234:0000:00001:C1C0:ABCD:0876", # extra 0 not allowed!
+ "2001:0000:1234:0000:0000:C1C0:ABCD:0876 0", # junk after valid address
+ "2001:0000:1234: 0000:0000:C1C0:ABCD:0876", # internal space
+ "3ffe:0b00:0000:0001:0000:0000:000a", # seven segments
+ "FF02:0000:0000:0000:0000:0000:0000:0000:0001", # nine segments
+ "3ffe:b00::1::a", # double "::"
+ "::1111:2222:3333:4444:5555:6666::", # double "::"
+ "1:2:3::4:5::7:8", # Double "::"
+ "12345::6:7:8",
+ # IPv4 embedded, but bad...
+ "1::5:400.2.3.4", "1::5:260.2.3.4", "1::5:256.2.3.4", "1::5:1.256.3.4",
+ "1::5:1.2.256.4", "1::5:1.2.3.256", "1::5:300.2.3.4", "1::5:1.300.3.4",
+ "1::5:1.2.300.4", "1::5:1.2.3.300", "1::5:900.2.3.4", "1::5:1.900.3.4",
+ "1::5:1.2.900.4", "1::5:1.2.3.900", "1::5:300.300.300.300", "1::5:3000.30.30.30",
+ "1::400.2.3.4", "1::260.2.3.4", "1::256.2.3.4", "1::1.256.3.4",
+ "1::1.2.256.4", "1::1.2.3.256", "1::300.2.3.4", "1::1.300.3.4",
+ "1::1.2.300.4", "1::1.2.3.300", "1::900.2.3.4", "1::1.900.3.4",
+ "1::1.2.900.4", "1::1.2.3.900", "1::300.300.300.300", "1::3000.30.30.30",
+ "::400.2.3.4", "::260.2.3.4", "::256.2.3.4", "::1.256.3.4",
+ "::1.2.256.4", "::1.2.3.256", "::300.2.3.4", "::1.300.3.4",
+ "::1.2.300.4", "::1.2.3.300", "::900.2.3.4", "::1.900.3.4",
+ "::1.2.900.4", "::1.2.3.900", "::300.300.300.300", "::3000.30.30.30",
+ "2001:1:1:1:1:1:255Z255X255Y255", # garbage instead of "." in IPv4
+ "::ffff:192x168.1.26", # ditto
+ "::ffff:2.3.4",
+ "::ffff:257.1.2.3",
+ "1.2.3.4:1111:2222:3333:4444::5555",
+ "1.2.3.4:1111:2222:3333::5555",
+ "1.2.3.4:1111:2222::5555",
+ "1.2.3.4:1111::5555",
+ "1.2.3.4::5555",
+ "1.2.3.4::",
+
+ # Testing IPv4 addresses represented as dotted-quads Leading zero's in
+ # IPv4 addresses not allowed: some systems treat the leading "0" in
+ # ".086" as the start of an octal number Update: The BNF in RFC-3986
+ # explicitly defines the dec-octet (for IPv4 addresses) not to have a
+ # leading zero
+ "fe80:0000:0000:0000:0204:61ff:254.157.241.086",
+ "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4",
+ "1111:2222:3333:4444:5555:6666:00.00.00.00",
+ "1111:2222:3333:4444:5555:6666:000.000.000.000",
+ "1111:2222:3333:4444:5555:6666:256.256.256.256",
+
+ "1111:2222:3333:4444::5555:",
+ "1111:2222:3333::5555:",
+ "1111:2222::5555:",
+ "1111::5555:",
+ "::5555:",
+ ":::",
+ "1111:",
+ ":",
+
+ ":1111:2222:3333:4444::5555",
+ ":1111:2222:3333::5555",
+ ":1111:2222::5555",
+ ":1111::5555",
+ ":::5555",
+ ":::",
+
+ # Additional test cases from http://rt.cpan.org/Public/Bug/Display.html?id=50693
+ "123",
+ "ldkfj",
+ "2001::FFD3::57ab",
+ "2001:db8:85a3::8a2e:37023:7334",
+ "2001:db8:85a3::8a2e:370k:7334",
+ "1:2:3:4:5:6:7:8:9",
+ "1::2::3",
+ "1:::3:4:5",
+ "1:2:3::4:5:6:7:8:9",
+
+ # Invalid data
+ "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX",
+
+ # Too many components
+ "1111:2222:3333:4444:5555:6666:7777:8888:9999",
+ "1111:2222:3333:4444:5555:6666:7777:8888::",
+ "::2222:3333:4444:5555:6666:7777:8888:9999",
+
+ # Too few components
+ "1111:2222:3333:4444:5555:6666:7777",
+ "1111:2222:3333:4444:5555:6666",
+ "1111:2222:3333:4444:5555",
+ "1111:2222:3333:4444",
+ "1111:2222:3333",
+ "1111:2222",
+ "1111",
+
+ # Missing :
+ "11112222:3333:4444:5555:6666:7777:8888",
+ "1111:22223333:4444:5555:6666:7777:8888",
+ "1111:2222:33334444:5555:6666:7777:8888",
+ "1111:2222:3333:44445555:6666:7777:8888",
+ "1111:2222:3333:4444:55556666:7777:8888",
+ "1111:2222:3333:4444:5555:66667777:8888",
+ "1111:2222:3333:4444:5555:6666:77778888",
+
+ # Missing : intended for ::
+ "1111:2222:3333:4444:5555:6666:7777:8888:",
+ "1111:2222:3333:4444:5555:6666:7777:",
+ "1111:2222:3333:4444:5555:6666:",
+ "1111:2222:3333:4444:5555:",
+ "1111:2222:3333:4444:",
+ "1111:2222:3333:",
+ "1111:2222:",
+ "1111:",
+ ":",
+ ":8888",
+ ":7777:8888",
+ ":6666:7777:8888",
+ ":5555:6666:7777:8888",
+ ":4444:5555:6666:7777:8888",
+ ":3333:4444:5555:6666:7777:8888",
+ ":2222:3333:4444:5555:6666:7777:8888",
+ ":1111:2222:3333:4444:5555:6666:7777:8888",
+
+ # :::
+ ":::2222:3333:4444:5555:6666:7777:8888",
+ "1111:::3333:4444:5555:6666:7777:8888",
+ "1111:2222:::4444:5555:6666:7777:8888",
+ "1111:2222:3333:::5555:6666:7777:8888",
+ "1111:2222:3333:4444:::6666:7777:8888",
+ "1111:2222:3333:4444:5555:::7777:8888",
+ "1111:2222:3333:4444:5555:6666:::8888",
+ "1111:2222:3333:4444:5555:6666:7777:::",
+
+ # Double ::",
+ "::2222::4444:5555:6666:7777:8888",
+ "::2222:3333::5555:6666:7777:8888",
+ "::2222:3333:4444::6666:7777:8888",
+ "::2222:3333:4444:5555::7777:8888",
+ "::2222:3333:4444:5555:7777::8888",
+ "::2222:3333:4444:5555:7777:8888::",
+
+ "1111::3333::5555:6666:7777:8888",
+ "1111::3333:4444::6666:7777:8888",
+ "1111::3333:4444:5555::7777:8888",
+ "1111::3333:4444:5555:6666::8888",
+ "1111::3333:4444:5555:6666:7777::",
+
+ "1111:2222::4444::6666:7777:8888",
+ "1111:2222::4444:5555::7777:8888",
+ "1111:2222::4444:5555:6666::8888",
+ "1111:2222::4444:5555:6666:7777::",
+
+ "1111:2222:3333::5555::7777:8888",
+ "1111:2222:3333::5555:6666::8888",
+ "1111:2222:3333::5555:6666:7777::",
+
+ "1111:2222:3333:4444::6666::8888",
+ "1111:2222:3333:4444::6666:7777::",
+
+ "1111:2222:3333:4444:5555::7777::",
+
+
+ # Too many components"
+ "1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4",
+ "1111:2222:3333:4444:5555:6666:7777:1.2.3.4",
+ "1111:2222:3333:4444:5555:6666::1.2.3.4",
+ "::2222:3333:4444:5555:6666:7777:1.2.3.4",
+ "1111:2222:3333:4444:5555:6666:1.2.3.4.5",
+
+ # Too few components
+ "1111:2222:3333:4444:5555:1.2.3.4",
+ "1111:2222:3333:4444:1.2.3.4",
+ "1111:2222:3333:1.2.3.4",
+ "1111:2222:1.2.3.4",
+ "1111:1.2.3.4",
+
+ # Missing :
+ "11112222:3333:4444:5555:6666:1.2.3.4",
+ "1111:22223333:4444:5555:6666:1.2.3.4",
+ "1111:2222:33334444:5555:6666:1.2.3.4",
+ "1111:2222:3333:44445555:6666:1.2.3.4",
+ "1111:2222:3333:4444:55556666:1.2.3.4",
+ "1111:2222:3333:4444:5555:66661.2.3.4",
+
+ # Missing .
+ "1111:2222:3333:4444:5555:6666:255255.255.255",
+ "1111:2222:3333:4444:5555:6666:255.255255.255",
+ "1111:2222:3333:4444:5555:6666:255.255.255255",
+
+ # Missing : intended for ::
+ ":1.2.3.4",
+ ":6666:1.2.3.4",
+ ":5555:6666:1.2.3.4",
+ ":4444:5555:6666:1.2.3.4",
+ ":3333:4444:5555:6666:1.2.3.4",
+ ":2222:3333:4444:5555:6666:1.2.3.4",
+ ":1111:2222:3333:4444:5555:6666:1.2.3.4",
+
+ # :::
+ ":::2222:3333:4444:5555:6666:1.2.3.4",
+ "1111:::3333:4444:5555:6666:1.2.3.4",
+ "1111:2222:::4444:5555:6666:1.2.3.4",
+ "1111:2222:3333:::5555:6666:1.2.3.4",
+ "1111:2222:3333:4444:::6666:1.2.3.4",
+ "1111:2222:3333:4444:5555:::1.2.3.4",
+
+ # Double ::
+ "::2222::4444:5555:6666:1.2.3.4",
+ "::2222:3333::5555:6666:1.2.3.4",
+ "::2222:3333:4444::6666:1.2.3.4",
+ "::2222:3333:4444:5555::1.2.3.4",
+
+ "1111::3333::5555:6666:1.2.3.4",
+ "1111::3333:4444::6666:1.2.3.4",
+ "1111::3333:4444:5555::1.2.3.4",
+
+ "1111:2222::4444::6666:1.2.3.4",
+ "1111:2222::4444:5555::1.2.3.4",
+
+ "1111:2222:3333::5555::1.2.3.4",
+
+ # Missing parts
+ "::.",
+ "::..",
+ "::...",
+ "::1...",
+ "::1.2..",
+ "::1.2.3.",
+ "::.2..",
+ "::.2.3.",
+ "::.2.3.4",
+ "::..3.",
+ "::..3.4",
+ "::...4",
+
+ # Extra : in front
+ ":1111:2222:3333:4444:5555:6666:7777::",
+ ":1111:2222:3333:4444:5555:6666::",
+ ":1111:2222:3333:4444:5555::",
+ ":1111:2222:3333:4444::",
+ ":1111:2222:3333::",
+ ":1111:2222::",
+ ":1111::",
+ ":::",
+ ":1111:2222:3333:4444:5555:6666::8888",
+ ":1111:2222:3333:4444:5555::8888",
+ ":1111:2222:3333:4444::8888",
+ ":1111:2222:3333::8888",
+ ":1111:2222::8888",
+ ":1111::8888",
+ ":::8888",
+ ":1111:2222:3333:4444:5555::7777:8888",
+ ":1111:2222:3333:4444::7777:8888",
+ ":1111:2222:3333::7777:8888",
+ ":1111:2222::7777:8888",
+ ":1111::7777:8888",
+ ":::7777:8888",
+ ":1111:2222:3333:4444::6666:7777:8888",
+ ":1111:2222:3333::6666:7777:8888",
+ ":1111:2222::6666:7777:8888",
+ ":1111::6666:7777:8888",
+ ":::6666:7777:8888",
+ ":1111:2222:3333::5555:6666:7777:8888",
+ ":1111:2222::5555:6666:7777:8888",
+ ":1111::5555:6666:7777:8888",
+ ":::5555:6666:7777:8888",
+ ":1111:2222::4444:5555:6666:7777:8888",
+ ":1111::4444:5555:6666:7777:8888",
+ ":::4444:5555:6666:7777:8888",
+ ":1111::3333:4444:5555:6666:7777:8888",
+ ":::3333:4444:5555:6666:7777:8888",
+ ":::2222:3333:4444:5555:6666:7777:8888",
+ ":1111:2222:3333:4444:5555:6666:1.2.3.4",
+ ":1111:2222:3333:4444:5555::1.2.3.4",
+ ":1111:2222:3333:4444::1.2.3.4",
+ ":1111:2222:3333::1.2.3.4",
+ ":1111:2222::1.2.3.4",
+ ":1111::1.2.3.4",
+ ":::1.2.3.4",
+ ":1111:2222:3333:4444::6666:1.2.3.4",
+ ":1111:2222:3333::6666:1.2.3.4",
+ ":1111:2222::6666:1.2.3.4",
+ ":1111::6666:1.2.3.4",
+ ":::6666:1.2.3.4",
+ ":1111:2222:3333::5555:6666:1.2.3.4",
+ ":1111:2222::5555:6666:1.2.3.4",
+ ":1111::5555:6666:1.2.3.4",
+ ":::5555:6666:1.2.3.4",
+ ":1111:2222::4444:5555:6666:1.2.3.4",
+ ":1111::4444:5555:6666:1.2.3.4",
+ ":::4444:5555:6666:1.2.3.4",
+ ":1111::3333:4444:5555:6666:1.2.3.4",
+ ":::2222:3333:4444:5555:6666:1.2.3.4",
+
+ # Extra : at end
+ "1111:2222:3333:4444:5555:6666:7777:::",
+ "1111:2222:3333:4444:5555:6666:::",
+ "1111:2222:3333:4444:5555:::",
+ "1111:2222:3333:4444:::",
+ "1111:2222:3333:::",
+ "1111:2222:::",
+ "1111:::",
+ ":::",
+ "1111:2222:3333:4444:5555:6666::8888:",
+ "1111:2222:3333:4444:5555::8888:",
+ "1111:2222:3333:4444::8888:",
+ "1111:2222:3333::8888:",
+ "1111:2222::8888:",
+ "1111::8888:",
+ "::8888:",
+ "1111:2222:3333:4444:5555::7777:8888:",
+ "1111:2222:3333:4444::7777:8888:",
+ "1111:2222:3333::7777:8888:",
+ "1111:2222::7777:8888:",
+ "1111::7777:8888:",
+ "::7777:8888:",
+ "1111:2222:3333:4444::6666:7777:8888:",
+ "1111:2222:3333::6666:7777:8888:",
+ "1111:2222::6666:7777:8888:",
+ "1111::6666:7777:8888:",
+ "::6666:7777:8888:",
+ "1111:2222:3333::5555:6666:7777:8888:",
+ "1111:2222::5555:6666:7777:8888:",
+ "1111::5555:6666:7777:8888:",
+ "::5555:6666:7777:8888:",
+ "1111:2222::4444:5555:6666:7777:8888:",
+ "1111::4444:5555:6666:7777:8888:",
+ "::4444:5555:6666:7777:8888:",
+ "1111::3333:4444:5555:6666:7777:8888:",
+ "::3333:4444:5555:6666:7777:8888:",
+ "::2222:3333:4444:5555:6666:7777:8888:",
+ ].each do |ip|
+ it "should reject #{ip.inspect} as an IPv6 address" do
+ expect { @class.new(:name => "foo", :ip => ip) }.to raise_error
+ end
+ end
+
it "should not accept spaces in resourcename" do
proc { @class.new(:name => "foo bar") }.should raise_error
end
diff --git a/spec/unit/type/schedule_spec.rb b/spec/unit/type/schedule_spec.rb
index b302d95cd..d407057a8 100755
--- a/spec/unit/type/schedule_spec.rb
+++ b/spec/unit/type/schedule_spec.rb
@@ -82,17 +82,17 @@ describe Puppet::Type.type(:schedule) do
it "should match when the start time is before the current time and the end time is after the current time" do
@schedule[:range] = "10:59:50 - 11:00:10"
- @schedule.should be_match
+ @schedule.must be_match
end
it "should not match when the start time is after the current time" do
@schedule[:range] = "11:00:05 - 11:00:10"
- @schedule.should_not be_match
+ @schedule.must_not be_match
end
it "should not match when the end time is previous to the current time" do
@schedule[:range] = "10:59:50 - 10:59:55"
- @schedule.should be_match
+ @schedule.must_not be_match
end
it "should throw an error if the upper limit is less than the lower limit" do
@@ -103,17 +103,17 @@ describe Puppet::Type.type(:schedule) do
it "should not match the current time fails between an array of ranges" do
@schedule[:range] = ["4-6", "20-23"]
- @schedule.should_not be_match
+ @schedule.must_not be_match
end
it "should match the lower array of ranges" do
@schedule[:range] = ["9-11", "14-16"]
- @schedule.should be_match
+ @schedule.must be_match
end
it "should match the upper array of ranges" do
@schedule[:range] = ["4-6", "11-12"]
- @schedule.should be_match
+ @schedule.must be_match
end
end
diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb
index 3b5f0cba6..5fa9f4534 100755
--- a/spec/unit/type_spec.rb
+++ b/spec/unit/type_spec.rb
@@ -588,6 +588,35 @@ describe Puppet::Type, :fails_on_windows => true do
resource.should_not be_suitable
end
end
+
+ describe "::ensurable?" do
+ before :each do
+ class TestEnsurableType < Puppet::Type
+ def exists?; end
+ def create; end
+ def destroy; end
+ end
+ end
+
+ it "is true if the class has exists?, create, and destroy methods defined" do
+ TestEnsurableType.should be_ensurable
+ end
+
+ it "is false if exists? is not defined" do
+ TestEnsurableType.class_eval { remove_method(:exists?) }
+ TestEnsurableType.should_not be_ensurable
+ end
+
+ it "is false if create is not defined" do
+ TestEnsurableType.class_eval { remove_method(:create) }
+ TestEnsurableType.should_not be_ensurable
+ end
+
+ it "is false if destroy is not defined" do
+ TestEnsurableType.class_eval { remove_method(:destroy) }
+ TestEnsurableType.should_not be_ensurable
+ end
+ end
end
describe Puppet::Type::RelationshipMetaparam do
diff --git a/spec/unit/util/anonymous_filelock_spec.rb b/spec/unit/util/anonymous_filelock_spec.rb
new file mode 100644
index 000000000..784ac0fca
--- /dev/null
+++ b/spec/unit/util/anonymous_filelock_spec.rb
@@ -0,0 +1,78 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/anonymous_filelock'
+
+describe Puppet::Util::AnonymousFilelock do
+ require 'puppet_spec/files'
+ include PuppetSpec::Files
+
+ before(:each) do
+ @lockfile = tmpfile("lock")
+ @lock = Puppet::Util::AnonymousFilelock.new(@lockfile)
+ end
+
+ it "should be anonymous" do
+ @lock.should be_anonymous
+ end
+
+ describe "#lock" do
+ it "should return false if already locked" do
+ @lock.stubs(:locked?).returns(true)
+ @lock.lock.should be_false
+ end
+
+ it "should return true if it successfully locked" do
+ @lock.lock.should be_true
+ end
+
+ it "should create a lock file" do
+ @lock.lock
+
+ File.should be_exists(@lockfile)
+ end
+
+ it "should create a lock file containing a message" do
+ @lock.lock("message")
+
+ File.read(@lockfile).should == "message"
+ end
+ end
+
+ describe "#unlock" do
+ it "should return true when unlocking" do
+ @lock.lock
+ @lock.unlock.should be_true
+ end
+
+ it "should return false when not locked" do
+ @lock.unlock.should be_false
+ end
+
+ it "should clear the lock file" do
+ File.open(@lockfile, 'w') { |fd| fd.print("locked") }
+ @lock.unlock
+ File.should_not be_exists(@lockfile)
+ end
+ end
+
+ it "should be locked when locked" do
+ @lock.lock
+ @lock.should be_locked
+ end
+
+ it "should not be locked when not locked" do
+ @lock.should_not be_locked
+ end
+
+ it "should not be locked when unlocked" do
+ @lock.lock
+ @lock.unlock
+ @lock.should_not be_locked
+ end
+
+ it "should return the lock message" do
+ @lock.lock("lock message")
+ @lock.message.should == "lock message"
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/execution_stub_spec.rb b/spec/unit/util/execution_stub_spec.rb
index 57305e315..b66f88f83 100755
--- a/spec/unit/util/execution_stub_spec.rb
+++ b/spec/unit/util/execution_stub_spec.rb
@@ -16,7 +16,8 @@ describe Puppet::Util::ExecutionStub do
Puppet::Util::ExecutionStub.current_value.should == nil
end
- it "should restore normal execution after 'reset' is called" do
+ # fails on windows, see #11740
+ it "should restore normal execution after 'reset' is called", :fails_on_windows => true do
# Note: "true" exists at different paths in different OSes
if Puppet.features.microsoft_windows?
true_command = [Puppet::Util.which('cmd.exe').tr('/', '\\'), '/c', 'exit 0']
diff --git a/spec/unit/util/instrumentation/data_spec.rb b/spec/unit/util/instrumentation/data_spec.rb
new file mode 100755
index 000000000..c2465f622
--- /dev/null
+++ b/spec/unit/util/instrumentation/data_spec.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+require 'matchers/json'
+require 'puppet/util/instrumentation'
+require 'puppet/util/instrumentation/data'
+
+describe Puppet::Util::Instrumentation::Data do
+ Puppet::Util::Instrumentation::Data
+
+ before(:each) do
+ @listener = stub 'listener', :name => "name"
+ Puppet::Util::Instrumentation.stubs(:[]).with("name").returns(@listener)
+ end
+
+ it "should indirect instrumentation_data" do
+ Puppet::Util::Instrumentation::Data.indirection.name.should == :instrumentation_data
+ end
+
+ it "should lookup the corresponding listener" do
+ Puppet::Util::Instrumentation.expects(:[]).with("name").returns(@listener)
+ Puppet::Util::Instrumentation::Data.new("name")
+ end
+
+ it "should error if the listener can not be found" do
+ Puppet::Util::Instrumentation.expects(:[]).with("name").returns(nil)
+ expect { Puppet::Util::Instrumentation::Data.new("name") }.to raise_error
+ end
+
+ it "should return pson data" do
+ data = Puppet::Util::Instrumentation::Data.new("name")
+ @listener.stubs(:data).returns({ :this_is_data => "here also" })
+ data.should set_json_attribute('name').to("name")
+ data.should set_json_attribute('this_is_data').to("here also")
+ end
+
+ it "should not error if the underlying listener doesn't have data" do
+ lambda { Puppet::Util::Instrumentation::Data.new("name").to_pson }.should_not raise_error
+ end
+
+ it "should return a hash containing data when unserializing from pson" do
+ Puppet::Util::Instrumentation::Data.from_pson({:name => "name"}).should == {:name => "name"}
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/indirection_probe_spec.rb b/spec/unit/util/instrumentation/indirection_probe_spec.rb
new file mode 100644
index 000000000..654825c9a
--- /dev/null
+++ b/spec/unit/util/instrumentation/indirection_probe_spec.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+require 'matchers/json'
+require 'puppet/util/instrumentation'
+require 'puppet/util/instrumentation/indirection_probe'
+
+describe Puppet::Util::Instrumentation::IndirectionProbe do
+ Puppet::Util::Instrumentation::IndirectionProbe
+
+ it "should indirect instrumentation_probe" do
+ Puppet::Util::Instrumentation::IndirectionProbe.indirection.name.should == :instrumentation_probe
+ end
+
+ it "should return pson data" do
+ probe = Puppet::Util::Instrumentation::IndirectionProbe.new("probe")
+ probe.should set_json_attribute('name').to("probe")
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/instrumentable_spec.rb b/spec/unit/util/instrumentation/instrumentable_spec.rb
new file mode 100755
index 000000000..dd2ad3084
--- /dev/null
+++ b/spec/unit/util/instrumentation/instrumentable_spec.rb
@@ -0,0 +1,186 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+
+require 'puppet/util/instrumentation'
+require 'puppet/util/instrumentation/instrumentable'
+
+describe Puppet::Util::Instrumentation::Instrumentable::Probe do
+
+ before(:each) do
+ Puppet::Util::Instrumentation.stubs(:start)
+ Puppet::Util::Instrumentation.stubs(:stop)
+
+ class ProbeTest
+ def mymethod(arg1, arg2, arg3)
+ :it_worked
+ end
+ end
+ end
+
+ after(:each) do
+ if ProbeTest.method_defined?(:instrumented_mymethod)
+ ProbeTest.class_eval {
+ remove_method(:mymethod)
+ alias_method(:mymethod, :instrumented_mymethod)
+ }
+ end
+ Puppet::Util::Instrumentation::Instrumentable.clear_probes
+ end
+
+ describe "when enabling a probe" do
+ it "should raise an error if the probe is already enabled" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ lambda { probe.enable }.should raise_error
+ end
+
+ it "should rename the original method name" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ ProbeTest.new.should respond_to(:instrumented_mymethod)
+ end
+
+ it "should create a new method of the original name" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ ProbeTest.new.should respond_to(:mymethod)
+ end
+ end
+
+ describe "when disabling a probe" do
+ it "should raise an error if the probe is already enabled" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ lambda { probe.disable }.should raise_error
+ end
+
+ it "should rename the original method name" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ probe.disable
+
+ Puppet::Util::Instrumentation.expects(:start).never
+ Puppet::Util::Instrumentation.expects(:stop).never
+ ProbeTest.new.mymethod(1,2,3).should == :it_worked
+ end
+
+ it "should remove the created method" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ probe.disable
+ ProbeTest.new.should_not respond_to(:instrumented_mymethod)
+ end
+ end
+
+ describe "when a probe is called" do
+ it "should call the original method" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ test = ProbeTest.new
+ test.expects(:instrumented_mymethod).with(1,2,3)
+ test.mymethod(1,2,3)
+ end
+
+ it "should start the instrumentation" do
+ Puppet::Util::Instrumentation.expects(:start)
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ test = ProbeTest.new
+ test.mymethod(1,2,3)
+ end
+
+ it "should stop the instrumentation" do
+ Puppet::Util::Instrumentation.expects(:stop)
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ test = ProbeTest.new
+ test.mymethod(1,2,3)
+ end
+
+ describe "and the original method raises an exception" do
+ it "should propagate the exception" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ test = ProbeTest.new
+ test.expects(:instrumented_mymethod).with(1,2,3).raises
+ lambda { test.mymethod(1,2,3) }.should raise_error
+ end
+
+ it "should stop the instrumentation" do
+ Puppet::Util::Instrumentation.expects(:stop)
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest)
+ probe.enable
+ test = ProbeTest.new
+ test.expects(:instrumented_mymethod).with(1,2,3).raises
+ lambda { test.mymethod(1,2,3) }.should raise_error
+ end
+ end
+
+ describe "with a static label" do
+ it "should send the label to the instrumentation layer" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest, :label => :mylabel)
+ probe.enable
+ test = ProbeTest.new
+ Puppet::Util::Instrumentation.expects(:start).with { |label,data| label == :mylabel }.returns(42)
+ Puppet::Util::Instrumentation.expects(:stop).with(:mylabel, 42, {})
+ test.mymethod(1,2,3)
+ end
+ end
+
+ describe "with a dynamic label" do
+ it "should send the evaluated label to the instrumentation layer" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest, :label => Proc.new { |parent,args| "dynamic#{args[0]}" } )
+ probe.enable
+ test = ProbeTest.new
+ Puppet::Util::Instrumentation.expects(:start).with { |label,data| label == "dynamic1" }.returns(42)
+ Puppet::Util::Instrumentation.expects(:stop).with("dynamic1",42,{})
+ test.mymethod(1,2,3)
+ end
+ end
+
+ describe "with static data" do
+ it "should send the data to the instrumentation layer" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest, :data => { :static_data => "nothing" })
+ probe.enable
+ test = ProbeTest.new
+ Puppet::Util::Instrumentation.expects(:start).with { |label,data| data == { :static_data => "nothing" }}
+ test.mymethod(1,2,3)
+ end
+ end
+
+ describe "with dynamic data" do
+ it "should send the evaluated label to the instrumentation layer" do
+ probe = Puppet::Util::Instrumentation::Instrumentable::Probe.new(:mymethod, ProbeTest, :data => Proc.new { |parent, args| { :key => args[0] } } )
+ probe.enable
+ test = ProbeTest.new
+ Puppet::Util::Instrumentation.expects(:start).with { |label,data| data == { :key => 1 } }
+ Puppet::Util::Instrumentation.expects(:stop)
+ test.mymethod(1,2,3)
+ end
+ end
+ end
+end
+
+describe Puppet::Util::Instrumentation::Instrumentable do
+ before(:each) do
+ class ProbeTest2
+ extend Puppet::Util::Instrumentation::Instrumentable
+ probe :mymethod
+ def mymethod(arg1,arg2,arg3)
+ end
+ end
+ end
+
+ after do
+ Puppet::Util::Instrumentation::Instrumentable.clear_probes
+ end
+
+ it "should allow probe definition" do
+ Puppet::Util::Instrumentation::Instrumentable.probe_names.should be_include("ProbeTest2.mymethod")
+ end
+
+ it "should be able to enable all probes" do
+ Puppet::Util::Instrumentation::Instrumentable.enable_probes
+ ProbeTest2.new.should respond_to(:instrumented_mymethod)
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/listener_spec.rb b/spec/unit/util/instrumentation/listener_spec.rb
new file mode 100755
index 000000000..bc49d265c
--- /dev/null
+++ b/spec/unit/util/instrumentation/listener_spec.rb
@@ -0,0 +1,100 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+require 'matchers/json'
+
+require 'puppet/util/instrumentation'
+require 'puppet/util/instrumentation/listener'
+
+describe Puppet::Util::Instrumentation::Listener do
+
+ Listener = Puppet::Util::Instrumentation::Listener
+
+ before(:each) do
+ @delegate = stub 'listener', :notify => nil, :name => 'listener'
+ @listener = Listener.new(@delegate)
+ @listener.enabled = true
+ end
+
+ it "should indirect instrumentation_listener" do
+ Listener.indirection.name.should == :instrumentation_listener
+ end
+
+ it "should raise an error if delegate doesn't support notify" do
+ lambda { Listener.new(Object.new) }.should raise_error
+ end
+
+ it "should not be enabled by default" do
+ Listener.new(@delegate).should_not be_enabled
+ end
+
+ it "should delegate notification" do
+ @delegate.expects(:notify).with(:event, :start, {})
+ listener = Listener.new(@delegate)
+ listener.notify(:event, :start, {})
+ end
+
+ it "should not listen is not enabled" do
+ @listener.enabled = false
+ @listener.should_not be_listen_to(:label)
+ end
+
+ it "should listen to all label if created without pattern" do
+ @listener.should be_listen_to(:improbable_label)
+ end
+
+ it "should listen to specific string pattern" do
+ listener = Listener.new(@delegate, "specific")
+ listener.enabled = true
+ listener.should be_listen_to(:specific)
+ end
+
+ it "should not listen to non-matching string pattern" do
+ listener = Listener.new(@delegate, "specific")
+ listener.enabled = true
+ listener.should_not be_listen_to(:unspecific)
+ end
+
+ it "should listen to specific regex pattern" do
+ listener = Listener.new(@delegate, /spe.*/)
+ listener.enabled = true
+ listener.should be_listen_to(:specific_pattern)
+ end
+
+ it "should not listen to non matching regex pattern" do
+ listener = Listener.new(@delegate, /^match.*/)
+ listener.enabled = true
+ listener.should_not be_listen_to(:not_matching)
+ end
+
+ it "should delegate its name to the underlying listener" do
+ @delegate.expects(:name).returns("myname")
+ @listener.name.should == "myname"
+ end
+
+ it "should delegate data fetching to the underlying listener" do
+ @delegate.expects(:data).returns(:data)
+ @listener.data.should == {:data => :data }
+ end
+
+ describe "when serializing to pson" do
+ it "should return a pson object containing pattern, name and status" do
+ @listener.should set_json_attribute('enabled').to(true)
+ @listener.should set_json_attribute('name').to("listener")
+ end
+ end
+
+ describe "when deserializing from pson" do
+ it "should lookup the archetype listener from the instrumentation layer" do
+ Puppet::Util::Instrumentation.expects(:[]).with("listener").returns(@listener)
+ Puppet::Util::Instrumentation::Listener.from_pson({"name" => "listener"})
+ end
+
+ it "should create a new listener shell instance delegating to the archetypal listener" do
+ Puppet::Util::Instrumentation.expects(:[]).with("listener").returns(@listener)
+ @listener.stubs(:listener).returns(@delegate)
+ Puppet::Util::Instrumentation::Listener.expects(:new).with(@delegate, nil, true)
+ Puppet::Util::Instrumentation::Listener.from_pson({"name" => "listener", "enabled" => true})
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/listeners/log_spec.rb b/spec/unit/util/instrumentation/listeners/log_spec.rb
new file mode 100755
index 000000000..8359625a1
--- /dev/null
+++ b/spec/unit/util/instrumentation/listeners/log_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+require 'puppet/util/instrumentation'
+
+Puppet::Util::Instrumentation.init
+log = Puppet::Util::Instrumentation.listener(:log)
+
+describe log do
+ before(:each) do
+ @log = log.new
+ end
+
+ it "should have a notify method" do
+ @log.should respond_to(:notify)
+ end
+
+ it "should have a data method" do
+ @log.should respond_to(:data)
+ end
+
+ it "should keep data for stop event" do
+ @log.notify(:test, :stop, { :started => Time.at(123456789), :finished => Time.at(123456790)})
+ @log.data.should == {:test=>["test took 1.0"]}
+ end
+
+ it "should not keep data for start event" do
+ @log.notify(:test, :start, { :started => Time.at(123456789)})
+ @log.data.should be_empty
+ end
+
+ it "should not keep more than 20 events per label" do
+ 25.times { @log.notify(:test, :stop, { :started => Time.at(123456789), :finished => Time.at(123456790)}) }
+ @log.data[:test].size.should == 20
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/listeners/performance_spec.rb b/spec/unit/util/instrumentation/listeners/performance_spec.rb
new file mode 100755
index 000000000..4cecbe3f6
--- /dev/null
+++ b/spec/unit/util/instrumentation/listeners/performance_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+require 'puppet/util/instrumentation'
+
+Puppet::Util::Instrumentation.init
+performance = Puppet::Util::Instrumentation.listener(:performance)
+
+describe performance do
+ before(:each) do
+ @performance = performance.new
+ end
+
+ it "should have a notify method" do
+ @performance.should respond_to(:notify)
+ end
+
+ it "should have a data method" do
+ @performance.should respond_to(:data)
+ end
+
+ it "should keep data for stop event" do
+ @performance.notify(:test, :stop, { :started => Time.at(123456789), :finished => Time.at(123456790)})
+ @performance.data.should == {:test=>{:average=>1.0, :count=>1, :min=>1.0, :max=>1.0, :sum=>1.0}}
+ end
+
+ it "should accumulate performance statistics" do
+ @performance.notify(:test, :stop, { :started => Time.at(123456789), :finished => Time.at(123456790)})
+ @performance.notify(:test, :stop, { :started => Time.at(123456789), :finished => Time.at(123456791)})
+
+ @performance.data.should == {:test=>{:average=>1.5, :count=>2, :min=>1.0, :max=>2.0, :sum=>3.0}}
+ end
+
+ it "should not keep data for start event" do
+ @performance.notify(:test, :start, { :started => Time.at(123456789)})
+ @performance.data.should be_empty
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation/listeners/process_name_spec.rb b/spec/unit/util/instrumentation/listeners/process_name_spec.rb
new file mode 100755
index 000000000..521257214
--- /dev/null
+++ b/spec/unit/util/instrumentation/listeners/process_name_spec.rb
@@ -0,0 +1,201 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+require 'puppet/util/instrumentation'
+
+Puppet::Util::Instrumentation.init
+process_name = Puppet::Util::Instrumentation.listener(:process_name)
+
+describe process_name do
+ before(:each) do
+ @process_name = process_name.new
+ end
+
+ it "should have a notify method" do
+ @process_name.should respond_to(:notify)
+ end
+
+ it "should not have a data method" do
+ @process_name.should_not respond_to(:data)
+ end
+
+ describe "when managing thread activity" do
+ before(:each) do
+ @process_name.stubs(:setproctitle)
+ @process_name.stubs(:base).returns("base")
+ end
+
+ it "should be able to append activity" do
+ thread1 = stub 'thread1'
+ @process_name.push_activity(:thread1,"activity1")
+ @process_name.push_activity(:thread1,"activity2")
+
+ @process_name.reason[:thread1].should == ["activity1", "activity2"]
+ end
+
+ it "should be able to remove activity" do
+ @process_name.push_activity(:thread1,"activity1")
+ @process_name.push_activity(:thread1,"activity1")
+ @process_name.pop_activity(:thread1)
+
+ @process_name.reason[:thread1].should == ["activity1"]
+ end
+
+ it "should maintain activity thread by thread" do
+ @process_name.push_activity(:thread1,"activity1")
+ @process_name.push_activity(:thread2,"activity2")
+
+ @process_name.reason[:thread1].should == ["activity1"]
+ @process_name.reason[:thread2].should == ["activity2"]
+ end
+
+ it "should set process title" do
+ @process_name.expects(:setproctitle)
+
+ @process_name.push_activity("thread1","activity1")
+ end
+ end
+
+ describe "when computing the current process name" do
+ before(:each) do
+ @process_name.stubs(:setproctitle)
+ @process_name.stubs(:base).returns("base")
+ end
+
+ it "should include every running thread activity" do
+ thread1 = stub 'thread1', :inspect => "\#<Thread:0xdeadbeef run>", :hash => 1
+ thread2 = stub 'thread2', :inspect => "\#<Thread:0x12344321 run>", :hash => 0
+
+ @process_name.push_activity(thread1,"Compiling node1.domain.com")
+ @process_name.push_activity(thread2,"Compiling node4.domain.com")
+ @process_name.push_activity(thread1,"Parsing file site.pp")
+ @process_name.push_activity(thread2,"Parsing file node.pp")
+
+ @process_name.process_name.should =~ /12344321 Compiling node4.domain.com,Parsing file node.pp/
+ @process_name.process_name.should =~ /deadbeef Compiling node1.domain.com,Parsing file site.pp/
+ end
+ end
+
+ describe "when finding base process name" do
+ {:master => "master", :agent => "agent", :user => "puppet"}.each do |program,base|
+ it "should return #{base} for #{program}" do
+ Puppet.run_mode.stubs(:name).returns(program)
+ @process_name.base.should == base
+ end
+ end
+ end
+
+ describe "when finding a thread id" do
+ it "should return the id from the thread inspect string" do
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
+ @process_name.thread_id(thread).should == "1234abdc"
+ end
+ end
+
+ describe "when scrolling the instrumentation string" do
+ it "should rotate the string of various step" do
+ @process_name.rotate("this is a rotation", 10).should == "rotation -- this is a "
+ end
+
+ it "should not rotate the string for the 0 offset" do
+ @process_name.rotate("this is a rotation", 0).should == "this is a rotation"
+ end
+ end
+
+ describe "when setting process name" do
+ before(:each) do
+ @process_name.stubs(:process_name).returns("12345 activity")
+ @process_name.stubs(:base).returns("base")
+ @oldname = $0
+ end
+
+ after(:each) do
+ $0 = @oldname
+ end
+
+ it "should do it if the feature is enabled" do
+ @process_name.setproctitle
+
+ $0.should == "base: 12345 activity"
+ end
+ end
+
+ describe "when subscribed" do
+ before(:each) do
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
+ Thread.stubs(:current).returns(thread)
+ end
+
+ it "should start the scroller" do
+ Thread.expects(:new)
+ @process_name.subscribed
+ end
+ end
+
+ describe "when unsubscribed" do
+ before(:each) do
+ @thread = stub 'scroller', :inspect => "\#<Thread:0x1234abdc run>"
+ Thread.stubs(:new).returns(@thread)
+ Thread.stubs(:kill)
+ @oldname = $0
+ @process_name.subscribed
+ end
+
+ after(:each) do
+ $0 = @oldname
+ end
+
+ it "should stop the scroller" do
+ Thread.expects(:kill).with(@thread)
+ @process_name.unsubscribed
+ end
+
+ it "should reset the process name" do
+ $0 = "let's see what happens"
+ @process_name.unsubscribed
+ $0.should == @oldname
+ end
+ end
+
+ describe "when setting a probe" do
+ before(:each) do
+ thread = stub 'thread', :inspect => "\#<Thread:0x1234abdc run>"
+ Thread.stubs(:current).returns(thread)
+ Thread.stubs(:new)
+ @process_name.active = true
+ end
+
+ it "should push current thread activity and execute the block" do
+ @process_name.notify(:instrumentation, :start, {})
+ $0.should == "puppet: 1234abdc instrumentation"
+ @process_name.notify(:instrumentation, :stop, {})
+ end
+
+ it "should finally pop the activity" do
+ @process_name.notify(:instrumentation, :start, {})
+ @process_name.notify(:instrumentation, :stop, {})
+ $0.should == "puppet: "
+ end
+ end
+
+ describe "when scrolling" do
+ it "should do nothing for shorter process names" do
+ @process_name.expects(:setproctitle).never
+ @process_name.scroll
+ end
+
+ it "should call setproctitle" do
+ @process_name.stubs(:process_name).returns("x" * 60)
+ @process_name.expects(:setproctitle)
+ @process_name.scroll
+ end
+
+ it "should increment rotation offset" do
+ name = "x" * 60
+ @process_name.stubs(:process_name).returns(name)
+ @process_name.expects(:rotate).once.with(name,1).returns("")
+ @process_name.expects(:rotate).once.with(name,2).returns("")
+ @process_name.scroll
+ @process_name.scroll
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/instrumentation_spec.rb b/spec/unit/util/instrumentation_spec.rb
new file mode 100755
index 000000000..0d19ee03c
--- /dev/null
+++ b/spec/unit/util/instrumentation_spec.rb
@@ -0,0 +1,181 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+
+require 'puppet/util/instrumentation'
+
+describe Puppet::Util::Instrumentation do
+
+ Instrumentation = Puppet::Util::Instrumentation
+
+ after(:each) do
+ Instrumentation.clear
+ end
+
+ it "should instance-load instrumentation listeners" do
+ Instrumentation.instance_loader(:listener).should be_instance_of(Puppet::Util::Autoload)
+ end
+
+ it "should have a method for registering instrumentation listeners" do
+ Instrumentation.should respond_to(:new_listener)
+ end
+
+ it "should have a method for retrieving instrumentation listener by name" do
+ Instrumentation.should respond_to(:listener)
+ end
+
+ describe "when registering listeners" do
+ it "should evaluate the supplied block as code for a class" do
+ Instrumentation.expects(:genclass).returns(Class.new { def notify(label, event, data) ; end })
+ Instrumentation.new_listener(:testing, :label_pattern => :for_this_label, :event => :all) { }
+ end
+
+ it "should subscribe a new listener instance" do
+ Instrumentation.expects(:genclass).returns(Class.new { def notify(label, event, data) ; end })
+ Instrumentation.new_listener(:testing, :label_pattern => :for_this_label, :event => :all) { }
+ Instrumentation.listeners.size.should == 1
+ Instrumentation.listeners[0].pattern.should == "for_this_label"
+ end
+
+ it "should be possible to access listeners by name" do
+ Instrumentation.expects(:genclass).returns(Class.new { def notify(label, event, data) ; end })
+ Instrumentation.new_listener(:testing, :label_pattern => :for_this_label, :event => :all) { }
+ Instrumentation["testing"].should_not be_nil
+ end
+
+ it "should be possible to store a new listener by name" do
+ listener = stub 'listener'
+ Instrumentation["testing"] = listener
+ Instrumentation["testing"].should == listener
+ end
+
+ it "should fail if listener is already subscribed" do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+ expect { Instrumentation.subscribe(listener, :for_this_label, :all) }.to raise_error
+ end
+
+ it 'should call #unsubscribed' do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+
+ listener.expects(:subscribed)
+
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+ end
+ end
+
+ describe "when unsubscribing listener" do
+ it "should remove it from the listeners" do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+ Instrumentation.unsubscribe(listener)
+ Instrumentation.listeners.size.should == 0
+ end
+
+ it "should warn if the listener wasn't subscribed" do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Puppet.expects(:warning)
+ Instrumentation.unsubscribe(listener)
+ end
+
+ it 'should call #unsubscribed' do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+
+ listener.expects(:unsubscribed)
+
+ Instrumentation.unsubscribe(listener)
+ end
+ end
+
+ describe "when firing events" do
+ it "should be able to find all listeners matching a label" do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+ Instrumentation.listeners[0].enabled = true
+
+ count = 0
+ Instrumentation.each_listener(:for_this_label) { |l| count += 1 }
+ count.should == 1
+ end
+
+ it "should fire events to matching listeners" do
+ listener = stub 'listener', :notify => nil, :name => "mylistener"
+ Instrumentation.subscribe(listener, :for_this_label, :all)
+ Instrumentation.listeners[0].enabled = true
+
+ listener.expects(:notify).with(:for_this_label, :start, {})
+
+ Instrumentation.publish(:for_this_label, :start, {})
+ end
+
+ it "should not fire events to non-matching listeners" do
+ listener1 = stub 'listener1', :notify => nil, :name => "mylistener1"
+ listener2 = stub 'listener2', :notify => nil, :name => "mylistener2"
+ Instrumentation.subscribe(listener1, :for_this_label, :all)
+ Instrumentation.listeners[0].enabled = true
+ Instrumentation.subscribe(listener2, :for_this_other_label, :all)
+ Instrumentation.listeners[1].enabled = true
+
+ listener1.expects(:notify).never
+ listener2.expects(:notify).with(:for_this_other_label, :start, {})
+
+ Instrumentation.publish(:for_this_other_label, :start, {})
+ end
+ end
+
+ describe "when instrumenting code" do
+ before(:each) do
+ Instrumentation.stubs(:publish)
+ end
+ describe "with a block" do
+ it "should execute it" do
+ executed = false
+ Instrumentation.instrument(:event) do
+ executed = true
+ end
+ executed.should be_true
+ end
+
+ it "should publish an event before execution" do
+ Instrumentation.expects(:publish).with { |label,event,data| label == :event && event == :start }
+ Instrumentation.instrument(:event) {}
+ end
+
+ it "should publish an event after execution" do
+ Instrumentation.expects(:publish).with { |label,event,data| label == :event && event == :stop }
+ Instrumentation.instrument(:event) {}
+ end
+
+ it "should publish the event even when block raised an exception" do
+ Instrumentation.expects(:publish).with { |label,event,data| label == :event }
+ lambda { Instrumentation.instrument(:event) { raise "not working" } }.should raise_error
+ end
+
+ it "should retain start end finish time of the event" do
+ Instrumentation.expects(:publish).with { |label,event,data| data.include?(:started) and data.include?(:finished) }
+ Instrumentation.instrument(:event) {}
+ end
+ end
+
+ describe "without a block" do
+ it "should raise an error if stop is called with no matching start" do
+ lambda{ Instrumentation.stop(:event) }.should raise_error
+ end
+
+ it "should publish an event on stop" do
+ Instrumentation.expects(:publish).with { |label,event,data| event == :start }
+ Instrumentation.expects(:publish).with { |label,event,data| event == :stop and data.include?(:started) and data.include?(:finished) }
+ data = {}
+ Instrumentation.start(:event, data)
+ Instrumentation.stop(:event, 1, data)
+ end
+
+ it "should return a different id per event" do
+ data = {}
+ Instrumentation.start(:event, data).should == 1
+ Instrumentation.start(:event, data).should == 2
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/pidlock_spec.rb b/spec/unit/util/pidlock_spec.rb
new file mode 100644
index 000000000..37f3ca4f4
--- /dev/null
+++ b/spec/unit/util/pidlock_spec.rb
@@ -0,0 +1,182 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/pidlock'
+
+describe Puppet::Util::Pidlock do
+ require 'puppet_spec/files'
+ include PuppetSpec::Files
+
+ before(:each) do
+ @lockfile = tmpfile("lock")
+ @lock = Puppet::Util::Pidlock.new(@lockfile)
+ end
+
+ it "should not be anonymous" do
+ @lock.should_not be_anonymous
+ end
+
+ describe "#lock" do
+ it "should not be locked at start" do
+ @lock.should_not be_locked
+ end
+
+ it "should not be mine at start" do
+ @lock.should_not be_mine
+ end
+
+ it "should become locked" do
+ @lock.lock
+ @lock.should be_locked
+ end
+
+ it "should become mine" do
+ @lock.lock
+ @lock.should be_mine
+ end
+
+ it "should be possible to lock multiple times" do
+ @lock.lock
+ lambda { @lock.lock }.should_not raise_error
+ end
+
+ it "should return true when locking" do
+ @lock.lock.should be_true
+ end
+
+ it "should return true if locked by me" do
+ @lock.lock
+ @lock.lock.should be_true
+ end
+
+ it "should return false if locked by someone else" do
+ Process.stubs(:kill)
+ File.open(@lockfile, "w") { |fd| fd.print('0') }
+
+ @lock.lock.should be_false
+ end
+
+ it "should create a lock file" do
+ @lock.lock
+ File.should be_exists(@lockfile)
+ end
+
+ it "should create a lock file containing our pid" do
+ @lock.lock
+ File.read(@lockfile).to_i.should == Process.pid.to_i
+ end
+ end
+
+ describe "#unlock" do
+ it "should not be locked anymore" do
+ @lock.lock
+ @lock.unlock
+ @lock.should_not be_locked
+ end
+
+ it "should return false if not locked" do
+ @lock.unlock.should be_false
+ end
+
+ it "should return true if properly unlocked" do
+ @lock.lock
+ @lock.unlock.should be_true
+ end
+
+ it "should get rid of the lock file" do
+ @lock.lock
+ @lock.unlock
+ File.should_not be_exists(@lockfile)
+ end
+ end
+
+ describe "#locked?" do
+ it "should return true if locked" do
+ @lock.lock
+ @lock.should be_locked
+ end
+ end
+
+ describe "with a stale lock" do
+ before(:each) do
+ Process.stubs(:kill).with(0, 6789)
+ Process.stubs(:kill).with(0, 1234).raises(Errno::ESRCH)
+ Process.stubs(:pid).returns(6789)
+ File.open(@lockfile, 'w') { |fd| fd.write("1234") }
+ end
+
+ it "should not be locked" do
+ @lock.should_not be_locked
+ end
+
+ describe "#lock" do
+ it "should clear stale locks" do
+ @lock.locked?
+ File.should_not be_exists(@lockfile)
+ end
+
+ it "should replace with new locks" do
+ @lock.lock
+ File.should be_exists(@lockfile)
+ @lock.lock_pid.should == 6789
+ @lock.should be_mine
+ @lock.should be_locked
+ end
+ end
+
+ describe "#unlock" do
+ it "should not be allowed" do
+ @lock.unlock.should be_false
+ end
+
+ it "should not remove the lock file" do
+ @lock.unlock
+ File.should be_exists(@lockfile)
+ end
+ end
+ end
+
+ describe "with another process lock" do
+ before(:each) do
+ Process.stubs(:kill).with(0, 6789)
+ Process.stubs(:kill).with(0, 1234)
+ Process.stubs(:pid).returns(6789)
+ File.open(@lockfile, 'w') { |fd| fd.write("1234") }
+ end
+
+ it "should be locked" do
+ @lock.should be_locked
+ end
+
+ it "should not be mine" do
+ @lock.should_not be_mine
+ end
+
+ describe "#lock" do
+ it "should not be possible" do
+ @lock.lock.should be_false
+ end
+
+ it "should not overwrite the lock" do
+ @lock.lock
+ @lock.should_not be_mine
+ end
+ end
+
+ describe "#unlock" do
+ it "should not be possible" do
+ @lock.unlock.should be_false
+ end
+
+ it "should not remove the lock file" do
+ @lock.unlock
+ File.should be_exists(@lockfile)
+ end
+
+ it "should still not be our lock" do
+ @lock.unlock
+ @lock.should_not be_mine
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/unit/util/queue/stomp_spec.rb b/spec/unit/util/queue/stomp_spec.rb
index 6799becea..7730ab7cb 100755
--- a/spec/unit/util/queue/stomp_spec.rb
+++ b/spec/unit/util/queue/stomp_spec.rb
@@ -13,7 +13,7 @@ describe 'Puppet::Util::Queue::Stomp', :if => Puppet.features.stomp?, :'fails_on
before do
# So we make sure we never create a real client instance.
# Otherwise we'll try to connect, and that's bad.
- Stomp::Client.stubs(:new).returns stub("client")
+ Stomp::Client.stubs(:new).returns stub("client", :publish => true)
end
it 'should be registered with Puppet::Util::Queue as :stomp type' do
@@ -22,7 +22,7 @@ describe 'Puppet::Util::Queue::Stomp', :if => Puppet.features.stomp?, :'fails_on
describe "when initializing" do
it "should create a Stomp client instance" do
- Stomp::Client.expects(:new).returns stub("stomp_client")
+ Stomp::Client.expects(:new).returns stub("stomp_client", :publish => true)
Puppet::Util::Queue::Stomp.new
end
@@ -65,7 +65,7 @@ describe 'Puppet::Util::Queue::Stomp', :if => Puppet.features.stomp?, :'fails_on
describe "when publishing a message" do
before do
- @client = stub 'client'
+ @client = stub 'client', :publish => true
Stomp::Client.stubs(:new).returns @client
@queue = Puppet::Util::Queue::Stomp.new
end
@@ -84,11 +84,16 @@ describe 'Puppet::Util::Queue::Stomp', :if => Puppet.features.stomp?, :'fails_on
@client.expects(:publish).with { |queue, msg, options| options[:persistent] == true }
@queue.publish_message('fooqueue', 'Smite!')
end
+
+ it "should use send when the gem does not support publish" do
+ Stomp::Client.stubs(:new).returns(stub('client', :send => true))
+ Puppet::Util::Queue::Stomp.new.publish_message('fooqueue', 'Smite!')
+ end
end
describe "when subscribing to a queue" do
before do
- @client = stub 'client', :acknowledge => true
+ @client = stub 'client', :acknowledge => true, :publish => true
Stomp::Client.stubs(:new).returns @client
@queue = Puppet::Util::Queue::Stomp.new
end
diff --git a/spec/unit/util/rdoc/parser_spec.rb b/spec/unit/util/rdoc/parser_spec.rb
index 9c8cc7588..892b932b2 100755
--- a/spec/unit/util/rdoc/parser_spec.rb
+++ b/spec/unit/util/rdoc/parser_spec.rb
@@ -135,7 +135,7 @@ describe RDoc::Parser, :'fails_on_ruby_1.9.2' => true do
describe "when finding modules from filepath" do
before :each do
- Puppet::Module.stubs(:modulepath).returns("/path/to/modules")
+ Puppet::Node::Environment.any_instance.stubs(:modulepath).returns("/path/to/modules")
end
it "should return the module name for modulized puppet manifests" do
diff --git a/spec/unit/util/reference_spec.rb b/spec/unit/util/reference_spec.rb
index 219a673ef..aa16299c7 100644
--- a/spec/unit/util/reference_spec.rb
+++ b/spec/unit/util/reference_spec.rb
@@ -8,20 +8,30 @@ describe Puppet::Util::Reference do
Puppet::Util::Reference.newreference :testreference, :doc => "A peer of the type and configuration references, but with no useful information" do
my_term = "A term"
my_definition = <<-EOT
-The definition of this term.
-We should be able to handle multi-line definitions.
+ The definition of this term, marked by a colon and a space.
+ We should be able to handle multi-line definitions. Each subsequent
+ line should left-align with the first word character after the colon
+ used as the definition marker.
-We should be able to handle multi-paragraph definitions.
+ We should be able to handle multi-paragraph definitions.
+
+ Leading indentation should be stripped from the definition, which allows
+ us to indent the source string for cosmetic purposes.
EOT
my_fragment = markdown_definitionlist(my_term, my_definition)
end
Puppet::Util::Reference.reference(:testreference).send(:to_markdown, true)
my_fragment.should == <<-EOT
A term
-: The definition of this term.
- We should be able to handle multi-line definitions.
+: The definition of this term, marked by a colon and a space.
+ We should be able to handle multi-line definitions. Each subsequent
+ line should left-align with the first word character after the colon
+ used as the definition marker.
+
+ We should be able to handle multi-paragraph definitions.
- We should be able to handle multi-paragraph definitions.
+ Leading indentation should be stripped from the definition, which allows
+ us to indent the source string for cosmetic purposes.
EOT
end
diff --git a/spec/unit/util/retryaction_spec.rb b/spec/unit/util/retryaction_spec.rb
new file mode 100644
index 000000000..90f8e8eb2
--- /dev/null
+++ b/spec/unit/util/retryaction_spec.rb
@@ -0,0 +1,62 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/retryaction'
+
+describe Puppet::Util::RetryAction do
+ let (:exceptions) {{ Puppet::Error => 'Puppet Error Exception' }}
+
+ it 'should retry on any exception if no acceptable exceptions given' do
+ Puppet::Util::RetryAction.expects(:sleep).with( (((2 ** 1) -1) * 0.1) )
+ Puppet::Util::RetryAction.expects(:sleep).with( (((2 ** 2) -1) * 0.1) )
+
+ expect do
+ Puppet::Util::RetryAction.retry_action( :retries => 2 ) do
+ raise ArgumentError, 'Fake Failure'
+ end
+ end.to raise_exception(Puppet::Util::RetryAction::RetryException::RetriesExceeded)
+ end
+
+ it 'should retry on acceptable exceptions' do
+ Puppet::Util::RetryAction.expects(:sleep).with( (((2 ** 1) -1) * 0.1) )
+ Puppet::Util::RetryAction.expects(:sleep).with( (((2 ** 2) -1) * 0.1) )
+
+ expect do
+ Puppet::Util::RetryAction.retry_action( :retries => 2, :retry_exceptions => exceptions) do
+ raise Puppet::Error, 'Fake Failure'
+ end
+ end.to raise_exception(Puppet::Util::RetryAction::RetryException::RetriesExceeded)
+ end
+
+ it 'should not retry on unacceptable exceptions' do
+ Puppet::Util::RetryAction.expects(:sleep).never
+
+ expect do
+ Puppet::Util::RetryAction.retry_action( :retries => 2, :retry_exceptions => exceptions) do
+ raise ArgumentError
+ end
+ end.to raise_exception(ArgumentError)
+ end
+
+ it 'should succeed if nothing is raised' do
+ Puppet::Util::RetryAction.expects(:sleep).never
+
+ Puppet::Util::RetryAction.retry_action( :retries => 2) do
+ true
+ end
+ end
+
+ it 'should succeed if an expected exception is raised retried and succeeds' do
+ should_retry = nil
+ Puppet::Util::RetryAction.expects(:sleep).once
+
+ Puppet::Util::RetryAction.retry_action( :retries => 2, :retry_exceptions => exceptions) do
+ if should_retry
+ true
+ else
+ should_retry = true
+ raise Puppet::Error, 'Fake error'
+ end
+ end
+ end
+end
diff --git a/spec/unit/util/suidmanager_spec.rb b/spec/unit/util/suidmanager_spec.rb
index 45a351f1b..575762f3c 100755
--- a/spec/unit/util/suidmanager_spec.rb
+++ b/spec/unit/util/suidmanager_spec.rb
@@ -308,3 +308,22 @@ describe Puppet::Util::SUIDManager do
end
end
end
+
+describe 'Puppet::Util::SUIDManager#groups=' do
+ subject do
+ Puppet::Util::SUIDManager
+ end
+
+
+ it "(#3419) should rescue Errno::EINVAL on OS X" do
+ Process.expects(:groups=).raises(Errno::EINVAL, 'blew up')
+ subject.expects(:osx_maj_ver).returns('10.7').twice
+ subject.groups = ['list', 'of', 'groups']
+ end
+
+ it "(#3419) should fail if an Errno::EINVAL is raised NOT on OS X" do
+ Process.expects(:groups=).raises(Errno::EINVAL, 'blew up')
+ subject.expects(:osx_maj_ver).returns(false)
+ expect { subject.groups = ['list', 'of', 'groups'] }.should raise_error(Errno::EINVAL)
+ end
+end
diff --git a/spec/unit/util/symbolic_file_mode_spec.rb b/spec/unit/util/symbolic_file_mode_spec.rb
new file mode 100755
index 000000000..a6e9509f7
--- /dev/null
+++ b/spec/unit/util/symbolic_file_mode_spec.rb
@@ -0,0 +1,182 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+require 'puppet/util/symbolic_file_mode'
+
+describe Puppet::Util::SymbolicFileMode do
+ include Puppet::Util::SymbolicFileMode
+
+ describe "#valid_symbolic_mode?" do
+ %w{
+ 0 0000 1 1 7 11 77 111 777 11
+ 0 00000 01 01 07 011 077 0111 0777 011
+ = - + u= g= o= a= u+ g+ o+ a+ u- g- o- a- ugo= ugoa= ugugug=
+ a=,u=,g= a=,g+
+ =rwx +rwx -rwx
+ 644 go-w =rw,+X +X 755 u=rwx,go=rx u=rwx,go=u-w go= g=u-w
+ 755 0755
+ }.each do |input|
+ it "should treat #{input.inspect} as valid" do
+ valid_symbolic_mode?(input).should be_true
+ end
+ end
+
+ [0000, 0111, 0640, 0755, 0777].each do |input|
+ it "should treat the int #{input.to_s(8)} as value" do
+ valid_symbolic_mode?(input).should be_true
+ end
+ end
+
+ %w{
+ -1 -8 8 9 18 19 91 81 000000 11111 77777
+ 0-1 0-8 08 09 018 019 091 081 0000000 011111 077777
+ u g o a ug uo ua ag
+ }.each do |input|
+ it "should treat #{input.inspect} as invalid" do
+ valid_symbolic_mode?(input).should be_false
+ end
+ end
+ end
+
+ describe "#normalize_symbolic_mode" do
+ it "should turn an int into a string" do
+ normalize_symbolic_mode(12).should be_an_instance_of String
+ end
+
+ it "should not add a leading zero to an int" do
+ normalize_symbolic_mode(12).should_not =~ /^0/
+ end
+
+ it "should not add a leading zero to a string with a number" do
+ normalize_symbolic_mode("12").should_not =~ /^0/
+ end
+
+ it "should string a leading zero from a number" do
+ normalize_symbolic_mode("012").should == '12'
+ end
+
+ it "should pass through any other string" do
+ normalize_symbolic_mode("u=rwx").should == 'u=rwx'
+ end
+ end
+
+ describe "#symbolic_mode_to_int" do
+ {
+ "0654" => 00654,
+ "u+r" => 00400,
+ "g+r" => 00040,
+ "a+r" => 00444,
+ "a+x" => 00111,
+ "o+t" => 01000,
+ "o+t" => 01000,
+ ["o-t", 07777] => 06777,
+ ["a-x", 07777] => 07666,
+ ["a-rwx", 07777] => 07000,
+ ["ug-rwx", 07777] => 07007,
+ "a+x,ug-rwx" => 00001,
+ # My experimentation on debian suggests that +g ignores the sgid flag
+ ["a+g", 02060] => 02666,
+ # My experimentation on debian suggests that -g ignores the sgid flag
+ ["a-g", 02666] => 02000,
+ "g+x,a+g" => 00111,
+ # +X without exec set in the original should not set anything
+ "u+x,g+X" => 00100,
+ "g+X" => 00000,
+ # +X only refers to the original, *unmodified* file mode!
+ ["u+x,a+X", 0600] => 00700,
+ # Examples from the MacOS chmod(1) manpage
+ "0644" => 00644,
+ ["go-w", 07777] => 07755,
+ ["=rw,+X", 07777] => 07777,
+ ["=rw,+X", 07766] => 07777,
+ ["=rw,+X", 07676] => 07777,
+ ["=rw,+X", 07667] => 07777,
+ ["=rw,+X", 07666] => 07666,
+ "0755" => 00755,
+ "u=rwx,go=rx" => 00755,
+ "u=rwx,go=u-w" => 00755,
+ ["go=", 07777] => 07700,
+ ["g=u-w", 07777] => 07757,
+ ["g=u-w", 00700] => 00750,
+ ["g=u-w", 00600] => 00640,
+ ["g=u-w", 00500] => 00550,
+ ["g=u-w", 00400] => 00440,
+ ["g=u-w", 00300] => 00310,
+ ["g=u-w", 00200] => 00200,
+ ["g=u-w", 00100] => 00110,
+ ["g=u-w", 00000] => 00000,
+ # Cruel, but legal, use of the action set.
+ ["g=u+r-w", 0300] => 00350,
+ # Empty assignments.
+ ["u=", 00000] => 00000,
+ ["u=", 00600] => 00000,
+ ["ug=", 00000] => 00000,
+ ["ug=", 00600] => 00000,
+ ["ug=", 00660] => 00000,
+ ["ug=", 00666] => 00006,
+ ["=", 00000] => 00000,
+ ["=", 00666] => 00000,
+ ["+", 00000] => 00000,
+ ["+", 00124] => 00124,
+ ["-", 00000] => 00000,
+ ["-", 00124] => 00124,
+ }.each do |input, result|
+ from = input.is_a?(Array) ? "#{input[0]}, 0#{input[1].to_s(8)}" : input
+ it "should map #{from.inspect} to #{result.inspect}" do
+ symbolic_mode_to_int(*input).should == result
+ end
+ end
+
+ # Now, test some failure modes.
+ it "should fail if no mode is given" do
+ expect { symbolic_mode_to_int('') }.
+ to raise_error Puppet::Error, /empty mode string/
+ end
+
+ %w{u g o ug uo go ugo a uu u/x u!x u=r,,g=r}.each do |input|
+ it "should fail if no (valid) action is given: #{input.inspect}" do
+ expect { symbolic_mode_to_int(input) }.
+ to raise_error Puppet::Error, /Missing action/
+ end
+ end
+
+ %w{u+q u-rwF u+rw,g+rw,o+RW}.each do |input|
+ it "should fail with unknown op #{input.inspect}" do
+ expect { symbolic_mode_to_int(input) }.
+ to raise_error Puppet::Error, /Unknown operation/
+ end
+ end
+
+ it "should refuse to subtract the conditional execute op" do
+ expect { symbolic_mode_to_int("o-rwX") }.
+ to raise_error Puppet::Error, /only works with/
+ end
+
+ it "should refuse to set to the conditional execute op" do
+ expect { symbolic_mode_to_int("o=rwX") }.
+ to raise_error Puppet::Error, /only works with/
+ end
+
+ %w{8 08 9 09 118 119}.each do |input|
+ it "should fail for decimal modes: #{input.inspect}" do
+ expect { symbolic_mode_to_int(input) }.
+ to raise_error Puppet::Error, /octal/
+ end
+ end
+
+ it "should set the execute bit on a directory, without exec in original" do
+ symbolic_mode_to_int("u+X", 0444, true).to_s(8).should == "544"
+ symbolic_mode_to_int("g+X", 0444, true).to_s(8).should == "454"
+ symbolic_mode_to_int("o+X", 0444, true).to_s(8).should == "445"
+ symbolic_mode_to_int("+X", 0444, true).to_s(8).should == "555"
+ end
+
+ it "should set the execute bit on a file with exec in the original" do
+ symbolic_mode_to_int("+X", 0544).to_s(8).should == "555"
+ end
+
+ it "should not set the execute bit on a file without exec on the original even if set by earlier DSL" do
+ symbolic_mode_to_int("u+x,go+X", 0444).to_s(8).should == "544"
+ end
+ end
+end
diff --git a/spec/unit/util/zaml_spec.rb b/spec/unit/util/zaml_spec.rb
index d77cf99d2..858ae6044 100755
--- a/spec/unit/util/zaml_spec.rb
+++ b/spec/unit/util/zaml_spec.rb
@@ -1,4 +1,16 @@
#!/usr/bin/env rspec
+# encoding: UTF-8
+#
+# The above encoding line is a magic comment to set the default source encoding
+# of this file for the Ruby interpreter. It must be on the first or second
+# line of the file if an interpreter is in use. In Ruby 1.9 and later, the
+# source encoding determines the encoding of String and Regexp objects created
+# from this source file. This explicit encoding is important becuase otherwise
+# Ruby will pick an encoding based on LANG or LC_CTYPE environment variables.
+# These may be different from site to site so it's important for us to
+# establish a consistent behavior. For more information on M17n please see:
+# http://links.puppetlabs.com/understanding_m17n
+
require 'spec_helper'
require 'puppet/util/monkey_patches'
@@ -60,3 +72,28 @@ describe "Pure ruby yaml implementation" do
x2[2].should equal(x2)
end
end
+
+# Note, many of these tests will pass on Ruby 1.8 but fail on 1.9 if the patch
+# fix is not applied to Puppet or there's a regression. These version
+# dependant failures are intentional since the string encoding behavior changed
+# significantly in 1.9.
+describe "UTF-8 encoded String#to_yaml (Bug #11246)" do
+ # JJM All of these snowmen are different representations of the same
+ # UTF-8 encoded string.
+ let(:snowman) { 'Snowman: [☃]' }
+ let(:snowman_escaped) { "Snowman: [\xE2\x98\x83]" }
+
+ describe "UTF-8 String Literal" do
+ subject { snowman }
+
+ it "should serialize to YAML" do
+ subject.to_yaml
+ end
+ it "should serialize and deserialize to the same thing" do
+ YAML.load(subject.to_yaml).should == subject
+ end
+ it "should serialize and deserialize to a String compatible with a UTF-8 encoded Regexp" do
+ YAML.load(subject.to_yaml).should =~ /☃/u
+ end
+ end
+end