summaryrefslogtreecommitdiff
path: root/spec/unit
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit')
-rwxr-xr-xspec/unit/agent_spec.rb12
-rwxr-xr-xspec/unit/application/agent_spec.rb8
-rwxr-xr-xspec/unit/application/apply_spec.rb20
-rwxr-xr-xspec/unit/application/cert_spec.rb14
-rwxr-xr-xspec/unit/application/device_spec.rb2
-rwxr-xr-xspec/unit/application/filebucket_spec.rb2
-rwxr-xr-xspec/unit/application/inspect_spec.rb2
-rwxr-xr-xspec/unit/application_spec.rb24
-rwxr-xr-xspec/unit/configurer/downloader_spec.rb15
-rwxr-xr-xspec/unit/configurer/fact_handler_spec.rb23
-rwxr-xr-xspec/unit/configurer/plugin_handler_spec.rb9
-rwxr-xr-xspec/unit/configurer_spec.rb20
-rwxr-xr-xspec/unit/confine/exists_spec.rb (renamed from spec/unit/provider/confine/exists_spec.rb)24
-rwxr-xr-xspec/unit/confine/false_spec.rb (renamed from spec/unit/provider/confine/false_spec.rb)18
-rwxr-xr-xspec/unit/confine/feature_spec.rb (renamed from spec/unit/provider/confine/feature_spec.rb)20
-rwxr-xr-xspec/unit/confine/true_spec.rb (renamed from spec/unit/provider/confine/true_spec.rb)14
-rwxr-xr-xspec/unit/confine/variable_spec.rb (renamed from spec/unit/provider/confine/variable_spec.rb)32
-rwxr-xr-xspec/unit/confine_collection_spec.rb (renamed from spec/unit/provider/confine_collection_spec.rb)60
-rwxr-xr-xspec/unit/confine_spec.rb (renamed from spec/unit/provider/confine_spec.rb)22
-rwxr-xr-xspec/unit/confiner_spec.rb (renamed from spec/unit/provider/confiner_spec.rb)8
-rw-r--r--spec/unit/face/parser_spec.rb54
-rwxr-xr-xspec/unit/file_bucket/dipper_spec.rb4
-rwxr-xr-xspec/unit/file_serving/base_spec.rb41
-rwxr-xr-xspec/unit/file_serving/configuration_spec.rb14
-rwxr-xr-xspec/unit/file_serving/content_spec.rb19
-rwxr-xr-xspec/unit/file_serving/fileset_spec.rb84
-rwxr-xr-xspec/unit/file_serving/metadata_spec.rb86
-rwxr-xr-xspec/unit/file_serving/mount/file_spec.rb20
-rwxr-xr-xspec/unit/file_serving/mount/pluginfacts_spec.rb73
-rw-r--r--spec/unit/file_system/file_spec.rb486
-rw-r--r--spec/unit/file_system/tempfile_spec.rb48
-rwxr-xr-xspec/unit/graph/relationship_graph_spec.rb6
-rw-r--r--spec/unit/hiera_puppet_spec.rb4
-rwxr-xr-xspec/unit/indirector/catalog/compiler_spec.rb34
-rwxr-xr-xspec/unit/indirector/certificate_status/file_spec.rb70
-rw-r--r--spec/unit/indirector/data_binding/hiera_spec.rb97
-rwxr-xr-xspec/unit/indirector/direct_file_server_spec.rb12
-rwxr-xr-xspec/unit/indirector/facts/facter_spec.rb33
-rwxr-xr-xspec/unit/indirector/file_bucket_file/file_spec.rb113
-rwxr-xr-xspec/unit/indirector/file_metadata/file_spec.rb4
-rwxr-xr-xspec/unit/indirector/file_server_spec.rb8
-rw-r--r--spec/unit/indirector/hiera_spec.rb154
-rwxr-xr-xspec/unit/indirector/json_spec.rb8
-rwxr-xr-xspec/unit/indirector/key/file_spec.rb27
-rwxr-xr-xspec/unit/indirector/resource/ral_spec.rb7
-rwxr-xr-xspec/unit/indirector/resource/store_configs_spec.rb11
-rwxr-xr-xspec/unit/indirector/rest_spec.rb10
-rwxr-xr-xspec/unit/indirector/ssl_file_spec.rb31
-rwxr-xr-xspec/unit/indirector/yaml_spec.rb8
-rwxr-xr-xspec/unit/module_spec.rb58
-rw-r--r--spec/unit/module_tool/tar/gnu_spec.rb4
-rw-r--r--spec/unit/module_tool/tar/solaris_spec.rb4
-rw-r--r--spec/unit/module_tool/tar_spec.rb45
-rwxr-xr-xspec/unit/network/authconfig_spec.rb3
-rwxr-xr-xspec/unit/network/authentication_spec.rb4
-rwxr-xr-xspec/unit/network/format_handler_spec.rb4
-rwxr-xr-xspec/unit/network/formats_spec.rb24
-rw-r--r--spec/unit/network/http/connection_spec.rb275
-rwxr-xr-xspec/unit/network/http/handler_spec.rb67
-rwxr-xr-xspec/unit/network/http_pool_spec.rb13
-rwxr-xr-xspec/unit/node/environment_spec.rb166
-rwxr-xr-xspec/unit/node/facts_spec.rb23
-rwxr-xr-xspec/unit/node_spec.rb43
-rw-r--r--spec/unit/parameter/boolean_spec.rb34
-rw-r--r--spec/unit/parser/ast/resourceparam_spec.rb51
-rwxr-xr-xspec/unit/parser/compiler_spec.rb138
-rw-r--r--spec/unit/parser/eparser_adapter_spec.rb24
-rwxr-xr-xspec/unit/parser/files_spec.rb22
-rw-r--r--spec/unit/parser/functions/contain_spec.rb185
-rwxr-xr-xspec/unit/parser/functions/create_resources_spec.rb18
-rwxr-xr-xspec/unit/parser/functions/generate_spec.rb2
-rwxr-xr-xspec/unit/parser/functions_spec.rb4
-rwxr-xr-xspec/unit/parser/lexer_spec.rb2
-rw-r--r--spec/unit/parser/methods/collect_spec.rb153
-rw-r--r--spec/unit/parser/methods/each_spec.rb2
-rw-r--r--spec/unit/parser/methods/filter_spec.rb (renamed from spec/unit/parser/methods/select_spec.rb)22
-rwxr-xr-xspec/unit/parser/methods/foreach_spec.rb91
-rw-r--r--spec/unit/parser/methods/map_spec.rb95
-rw-r--r--spec/unit/parser/methods/reduce_spec.rb23
-rw-r--r--spec/unit/parser/methods/reject_spec.rb73
-rw-r--r--spec/unit/parser/methods/shared.rb10
-rw-r--r--spec/unit/parser/methods/slice_spec.rb26
-rwxr-xr-xspec/unit/parser/parser_spec.rb2
-rwxr-xr-xspec/unit/parser/resource/param_spec.rb44
-rwxr-xr-xspec/unit/parser/resource_spec.rb31
-rw-r--r--spec/unit/pops/model/ast_transformer_spec.rb22
-rwxr-xr-xspec/unit/pops/parser/lexer_spec.rb27
-rw-r--r--spec/unit/pops/parser/parse_calls_spec.rb10
-rw-r--r--spec/unit/pops/transformer/transform_calls_spec.rb12
-rw-r--r--spec/unit/pops/transformer/transform_containers_spec.rb4
-rw-r--r--spec/unit/pops/validator/validator_spec.rb31
-rwxr-xr-xspec/unit/provider/augeas/augeas_spec.rb59
-rwxr-xr-xspec/unit/provider/exec/posix_spec.rb11
-rwxr-xr-xspec/unit/provider/file/posix_spec.rb4
-rw-r--r--spec/unit/provider/group/windows_adsi_spec.rb75
-rwxr-xr-xspec/unit/provider/nameservice/directoryservice_spec.rb6
-rwxr-xr-xspec/unit/provider/package/apt_spec.rb2
-rwxr-xr-xspec/unit/provider/package/aptrpm_spec.rb2
-rwxr-xr-xspec/unit/provider/package/msi_spec.rb57
-rwxr-xr-xspec/unit/provider/package/openbsd_spec.rb6
-rwxr-xr-xspec/unit/provider/package/rpm_spec.rb79
-rwxr-xr-xspec/unit/provider/package/windows_spec.rb34
-rwxr-xr-xspec/unit/provider/package/yum_spec.rb2
-rwxr-xr-xspec/unit/provider/service/base_spec.rb2
-rwxr-xr-xspec/unit/provider/service/daemontools_spec.rb26
-rwxr-xr-xspec/unit/provider/service/freebsd_spec.rb6
-rwxr-xr-xspec/unit/provider/service/gentoo_spec.rb7
-rwxr-xr-xspec/unit/provider/service/init_spec.rb34
-rwxr-xr-xspec/unit/provider/service/launchd_spec.rb99
-rw-r--r--spec/unit/provider/service/openbsd_spec.rb125
-rwxr-xr-xspec/unit/provider/service/openwrt_spec.rb2
-rwxr-xr-xspec/unit/provider/service/runit_spec.rb17
-rwxr-xr-xspec/unit/provider/service/upstart_spec.rb8
-rwxr-xr-xspec/unit/provider/ssh_authorized_key/parsed_spec.rb10
-rwxr-xr-xspec/unit/provider/user/directoryservice_spec.rb8
-rwxr-xr-xspec/unit/provider/user/windows_adsi_spec.rb2
-rwxr-xr-xspec/unit/provider/zone/solaris_spec.rb2
-rwxr-xr-xspec/unit/provider_spec.rb4
-rwxr-xr-xspec/unit/reports/http_spec.rb53
-rwxr-xr-xspec/unit/reports/store_spec.rb4
-rwxr-xr-xspec/unit/resource/catalog_spec.rb92
-rw-r--r--spec/unit/resource/resource_type.json34
-rwxr-xr-xspec/unit/resource/status_spec.rb12
-rwxr-xr-xspec/unit/resource/type_spec.rb31
-rwxr-xr-xspec/unit/resource_spec.rb44
-rw-r--r--spec/unit/settings/autosign_setting_spec.rb46
-rwxr-xr-xspec/unit/settings/file_setting_spec.rb4
-rwxr-xr-xspec/unit/settings/path_setting_spec.rb4
-rwxr-xr-xspec/unit/settings/priority_setting_spec.rb66
-rwxr-xr-xspec/unit/settings_spec.rb74
-rw-r--r--spec/unit/ssl/certificate_authority/autosign_command_spec.rb30
-rwxr-xr-xspec/unit/ssl/certificate_authority_spec.rb263
-rwxr-xr-xspec/unit/ssl/certificate_factory_spec.rb18
-rw-r--r--spec/unit/ssl/certificate_request_attributes_spec.rb61
-rwxr-xr-xspec/unit/ssl/certificate_request_spec.rb103
-rwxr-xr-xspec/unit/ssl/certificate_spec.rb49
-rwxr-xr-xspec/unit/ssl/host_spec.rb42
-rwxr-xr-xspec/unit/ssl/inventory_spec.rb89
-rwxr-xr-xspec/unit/ssl/key_spec.rb8
-rw-r--r--spec/unit/ssl/oids_spec.rb48
-rw-r--r--spec/unit/ssl/validator_spec.rb55
-rwxr-xr-xspec/unit/status_spec.rb9
-rwxr-xr-xspec/unit/transaction/event_spec.rb10
-rwxr-xr-xspec/unit/transaction/report_spec.rb21
-rwxr-xr-xspec/unit/transaction/resource_harness_spec.rb270
-rwxr-xr-xspec/unit/transaction_spec.rb62
-rwxr-xr-xspec/unit/type/component_spec.rb4
-rwxr-xr-xspec/unit/type/exec_spec.rb21
-rwxr-xr-xspec/unit/type/file/content_spec.rb15
-rwxr-xr-xspec/unit/type/file/ctime_spec.rb2
-rwxr-xr-xspec/unit/type/file/mode_spec.rb50
-rwxr-xr-xspec/unit/type/file/mtime_spec.rb2
-rwxr-xr-xspec/unit/type/file/source_spec.rb184
-rwxr-xr-xspec/unit/type/file_spec.rb134
-rwxr-xr-xspec/unit/type/group_spec.rb20
-rwxr-xr-xspec/unit/type/k5login_spec.rb6
-rwxr-xr-xspec/unit/type/mount_spec.rb53
-rwxr-xr-xspec/unit/type/nagios_spec.rb216
-rwxr-xr-xspec/unit/type/package_spec.rb8
-rwxr-xr-xspec/unit/type/schedule_spec.rb6
-rwxr-xr-xspec/unit/type/service_spec.rb6
-rwxr-xr-xspec/unit/type/tidy_spec.rb28
-rwxr-xr-xspec/unit/type/user_spec.rb9
-rwxr-xr-xspec/unit/type_spec.rb90
-rwxr-xr-xspec/unit/util/adsi_spec.rb136
-rwxr-xr-xspec/unit/util/autoload_spec.rb28
-rwxr-xr-xspec/unit/util/backups_spec.rb50
-rwxr-xr-xspec/unit/util/checksums_spec.rb3
-rwxr-xr-xspec/unit/util/command_line_spec.rb41
-rw-r--r--spec/unit/util/docs_spec.rb91
-rwxr-xr-xspec/unit/util/execution_spec.rb32
-rwxr-xr-xspec/unit/util/filetype_spec.rb14
-rw-r--r--spec/unit/util/lockfile_spec.rb4
-rwxr-xr-xspec/unit/util/log/destinations_spec.rb32
-rwxr-xr-xspec/unit/util/monkey_patches_spec.rb41
-rw-r--r--spec/unit/util/pidlock_spec.rb12
-rwxr-xr-xspec/unit/util/rdoc/parser_spec.rb28
-rwxr-xr-xspec/unit/util/rdoc_spec.rb42
-rwxr-xr-xspec/unit/util/resource_template_spec.rb6
-rwxr-xr-xspec/unit/util/selinux_spec.rb6
-rwxr-xr-xspec/unit/util/storage_spec.rb8
-rwxr-xr-xspec/unit/util/suidmanager_spec.rb7
-rw-r--r--spec/unit/util/tag_set_spec.rb46
-rwxr-xr-xspec/unit/util/tagging_spec.rb127
-rw-r--r--spec/unit/util/watcher_spec.rb5
-rw-r--r--spec/unit/util/windows/access_control_entry_spec.rb67
-rw-r--r--spec/unit/util/windows/access_control_list_spec.rb133
-rwxr-xr-xspec/unit/util/windows/root_certs_spec.rb18
-rw-r--r--spec/unit/util/windows/security_descriptor_spec.rb117
-rwxr-xr-xspec/unit/util/windows/sid_spec.rb69
-rw-r--r--spec/unit/util/yaml_spec.rb14
-rwxr-xr-xspec/unit/util_spec.rb14
192 files changed, 5717 insertions, 2425 deletions
diff --git a/spec/unit/agent_spec.rb b/spec/unit/agent_spec.rb
index 536fb47de..38e53176d 100755
--- a/spec/unit/agent_spec.rb
+++ b/spec/unit/agent_spec.rb
@@ -135,18 +135,6 @@ describe Puppet::Agent do
@agent.run
end
- it "should use a mutex to restrict multi-threading" do
- client = AgentTestClient.new
- AgentTestClient.expects(:new).returns client
-
- mutex = mock 'mutex'
- @agent.expects(:sync).returns mutex
-
- mutex.expects(:synchronize)
- client.expects(:run).never # if it doesn't run, then we know our yield is what triggers it
- @agent.run
- end
-
it "should use a filesystem lock to restrict multiple processes running the agent" do
client = AgentTestClient.new
AgentTestClient.expects(:new).returns client
diff --git a/spec/unit/application/agent_spec.rb b/spec/unit/application/agent_spec.rb
index 2ec32dbfb..4280a953c 100755
--- a/spec/unit/application/agent_spec.rb
+++ b/spec/unit/application/agent_spec.rb
@@ -198,7 +198,7 @@ describe Puppet::Application::Agent do
describe "during setup" do
before :each do
Puppet.stubs(:info)
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet[:libdir] = "/dev/null/lib"
Puppet::Transaction::Report.indirection.stubs(:terminus_class=)
Puppet::Transaction::Report.indirection.stubs(:cache_class=)
@@ -449,8 +449,8 @@ describe Puppet::Application::Agent do
describe "when setting up listen" do
before :each do
- FileTest.stubs(:exists?).with('auth').returns(true)
- File.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with('auth').returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
@puppetd.options[:serve] = []
@server = stub_everything 'server'
Puppet::Network::Server.stubs(:new).returns(@server)
@@ -460,7 +460,7 @@ describe Puppet::Application::Agent do
it "should exit if no authorization file" do
Puppet[:listen] = true
Puppet.stubs(:err)
- FileTest.stubs(:exists?).with(Puppet[:rest_authconfig]).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).with(Puppet[:rest_authconfig]).returns(false)
expect do
execute_agent
diff --git a/spec/unit/application/apply_spec.rb b/spec/unit/application/apply_spec.rb
index 97728c06e..d3cc54884 100755
--- a/spec/unit/application/apply_spec.rb
+++ b/spec/unit/application/apply_spec.rb
@@ -45,8 +45,8 @@ describe Puppet::Application::Apply do
@apply.handle_logdest("console")
end
- it "should put the logset options to true" do
- @apply.options.expects(:[]=).with(:logset,true)
+ it "should set the setdest options to true" do
+ @apply.options.expects(:[]=).with(:setdest,true)
@apply.handle_logdest("console")
end
@@ -103,6 +103,22 @@ describe Puppet::Application::Apply do
@apply.setup
end
+ it "configures a profiler when profiling is enabled" do
+ Puppet[:profile] = true
+
+ @apply.setup
+
+ expect(Puppet::Util::Profiler.current).to be_a(Puppet::Util::Profiler::WallClock)
+ end
+
+ it "does not have a profiler if profiling is disabled" do
+ Puppet[:profile] = false
+
+ @apply.setup
+
+ expect(Puppet::Util::Profiler.current).to eq(Puppet::Util::Profiler::NONE)
+ end
+
it "should set default_file_terminus to `file_server` to be local" do
@apply.app_defaults[:default_file_terminus].should == :file_server
end
diff --git a/spec/unit/application/cert_spec.rb b/spec/unit/application/cert_spec.rb
index 25d74c859..f24ef8677 100755
--- a/spec/unit/application/cert_spec.rb
+++ b/spec/unit/application/cert_spec.rb
@@ -122,10 +122,12 @@ describe Puppet::Application::Cert => true do
@ca = stub_everything 'ca'
@cert_app.ca = @ca
@cert_app.command_line.stubs(:args).returns([])
+ @iface = stub_everything 'iface'
+ Puppet::SSL::CertificateAuthority::Interface.stubs(:new).returns(@iface)
end
it "should delegate to the CertificateAuthority" do
- @ca.expects(:apply)
+ @iface.expects(:apply)
@cert_app.main
end
@@ -133,7 +135,7 @@ describe Puppet::Application::Cert => true do
it "should delegate with :all if option --all was given" do
@cert_app.handle_all(0)
- @ca.expects(:apply).with { |cert_mode,to| to[:to] == :all }
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| to[:to] == :all }
@cert_app.main
end
@@ -141,7 +143,7 @@ describe Puppet::Application::Cert => true do
it "should delegate to ca.apply with the hosts given on command line" do
@cert_app.command_line.stubs(:args).returns(["host"])
- @ca.expects(:apply).with { |cert_mode,to| to[:to] == ["host"]}
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| to[:to] == ["host"]}
@cert_app.main
end
@@ -150,7 +152,7 @@ describe Puppet::Application::Cert => true do
@cert_app.command_line.stubs(:args).returns(["host"])
@cert_app.handle_digest(:digest)
- @ca.expects(:apply).with { |cert_mode,to| to[:digest] == :digest}
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| to[:digest] == :digest}
@cert_app.main
end
@@ -159,8 +161,8 @@ describe Puppet::Application::Cert => true do
@cert_app.subcommand = :destroy
@cert_app.command_line.stubs(:args).returns(["host"])
- @ca.expects(:apply).with { |cert_mode,to| cert_mode == :revoke }
- @ca.expects(:apply).with { |cert_mode,to| cert_mode == :destroy }
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| cert_mode == :revoke }
+ Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns(@iface).with { |cert_mode,to| cert_mode == :destroy }
@cert_app.main
end
diff --git a/spec/unit/application/device_spec.rb b/spec/unit/application/device_spec.rb
index 43787b69f..bbbc011c1 100755
--- a/spec/unit/application/device_spec.rb
+++ b/spec/unit/application/device_spec.rb
@@ -127,7 +127,7 @@ describe Puppet::Application::Device do
before :each do
@device.options.stubs(:[])
Puppet.stubs(:info)
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet[:libdir] = "/dev/null/lib"
Puppet::SSL::Host.stubs(:ca_location=)
Puppet::Transaction::Report.indirection.stubs(:terminus_class=)
diff --git a/spec/unit/application/filebucket_spec.rb b/spec/unit/application/filebucket_spec.rb
index e7702e45a..4301c7dcd 100755
--- a/spec/unit/application/filebucket_spec.rb
+++ b/spec/unit/application/filebucket_spec.rb
@@ -178,7 +178,7 @@ describe Puppet::Application::Filebucket do
it "should call the client backup method for each given parameter" do
@filebucket.stubs(:puts)
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:readable?).returns(true)
@filebucket.stubs(:args).returns(["file1", "file2"])
diff --git a/spec/unit/application/inspect_spec.rb b/spec/unit/application/inspect_spec.rb
index c0a034511..da73ee51c 100755
--- a/spec/unit/application/inspect_spec.rb
+++ b/spec/unit/application/inspect_spec.rb
@@ -36,7 +36,7 @@ describe Puppet::Application::Inspect do
describe "when executing" do
before :each do
Puppet[:report] = true
- @inspect.options[:logset] = true
+ @inspect.options[:setdest] = true
Puppet::Transaction::Report::Rest.any_instance.stubs(:save)
@inspect.setup
end
diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb
index 912416d53..1c9dd49b8 100755
--- a/spec/unit/application_spec.rb
+++ b/spec/unit/application_spec.rb
@@ -618,4 +618,28 @@ describe Puppet::Application do
end
end
+
+ describe "#handle_logdest_arg" do
+
+ let(:test_arg) { "arg_test_logdest" }
+
+ it "should log an exception that is raised" do
+ our_exception = Puppet::DevError.new("test exception")
+ Puppet::Util::Log.expects(:newdestination).with(test_arg).raises(our_exception)
+ Puppet.expects(:log_exception).with(our_exception)
+ @app.handle_logdest_arg(test_arg)
+ end
+
+ it "should set the new log destination" do
+ Puppet::Util::Log.expects(:newdestination).with(test_arg)
+ @app.handle_logdest_arg(test_arg)
+ end
+
+ it "should set the flag that a destination is set in the options hash" do
+ Puppet::Util::Log.stubs(:newdestination).with(test_arg)
+ @app.handle_logdest_arg(test_arg)
+ @app.options[:setdest].should be_true
+ end
+ end
+
end
diff --git a/spec/unit/configurer/downloader_spec.rb b/spec/unit/configurer/downloader_spec.rb
index 403e92c1a..a818370fc 100755
--- a/spec/unit/configurer/downloader_spec.rb
+++ b/spec/unit/configurer/downloader_spec.rb
@@ -51,11 +51,7 @@ describe Puppet::Configurer::Downloader do
@dler.file
end
- describe "on POSIX" do
- before :each do
- Puppet.features.stubs(:microsoft_windows?).returns false
- end
-
+ describe "on POSIX", :as_platform => :posix do
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 }
@@ -69,7 +65,7 @@ describe Puppet::Configurer::Downloader do
end
end
- describe "on Windows", :if => Puppet.features.microsoft_windows? do
+ describe "on Windows", :as_platform => :windows do
it "should omit the owner" do
Puppet::Type.type(:file).expects(:new).with { |opts| opts[:owner] == nil }
@dler.file
@@ -79,6 +75,11 @@ describe Puppet::Configurer::Downloader do
Puppet::Type.type(:file).expects(:new).with { |opts| opts[:group] == nil }
@dler.file
end
+
+ it "should set source_permissions to ignore" do
+ Puppet::Type.type(:file).expects(:new).with { |opts| opts[:source_permissions] == :ignore }
+ @dler.file
+ end
end
it "should always force the download" do
@@ -135,7 +136,7 @@ describe Puppet::Configurer::Downloader do
Puppet[:tags] = 'maytag'
@dler.evaluate
- File.exists?(@dl_name).should be_true
+ Puppet::FileSystem::File.exist?(@dl_name).should be_true
end
it "should log that it is downloading" do
diff --git a/spec/unit/configurer/fact_handler_spec.rb b/spec/unit/configurer/fact_handler_spec.rb
index a74a91dfa..a92ad7d4f 100755
--- a/spec/unit/configurer/fact_handler_spec.rb
+++ b/spec/unit/configurer/fact_handler_spec.rb
@@ -3,6 +3,16 @@ require 'spec_helper'
require 'puppet/configurer'
require 'puppet/configurer/fact_handler'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ describe "catalog facts schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, FACTS_SCHEMA)
+ end
+ end
+
+ end
+
class FactHandlerTester
include Puppet::Configurer::FactHandler
@@ -74,4 +84,17 @@ describe Puppet::Configurer::FactHandler do
@facthandler.facts_for_uploading.should == {:facts_format => :pson, :facts => text}
end
+
+ def validate_json_for_facts(catalog_facts)
+ JSON::Validator.validate!(FACTS_SCHEMA, catalog_facts)
+ end
+
+ it "should generate valid facts data against the facts schema", :unless => Puppet.features.microsoft_windows? do
+ facts = Puppet::Node::Facts.new(Puppet[:node_name_value], 'my_name_fact' => 'other_node_name')
+ Puppet::Node::Facts.indirection.save(facts)
+
+ validate_json_for_facts(CGI.unescape(@facthandler.facts_for_uploading[:facts]))
+ end
+
end
+
diff --git a/spec/unit/configurer/plugin_handler_spec.rb b/spec/unit/configurer/plugin_handler_spec.rb
index e5fda57e2..20027333d 100755
--- a/spec/unit/configurer/plugin_handler_spec.rb
+++ b/spec/unit/configurer/plugin_handler_spec.rb
@@ -19,7 +19,7 @@ describe Puppet::Configurer::PluginHandler do
it "should use an Agent Downloader, with the name, source, destination, ignore, and environment set correctly, to download plugins when downloading is enabled" do
downloader = mock 'downloader'
-
+ Puppet.features.stubs(:external_facts?).returns(:true)
# This is needed in order to make sure we pass on windows
plugindest = File.expand_path("/tmp/pdest")
@@ -27,9 +27,14 @@ describe Puppet::Configurer::PluginHandler do
Puppet[:plugindest] = plugindest
Puppet[:pluginsignore] = "pignore"
+ Puppet[:pluginfactsource] = "psource"
+ Puppet[:pluginfactdest] = plugindest
+
+ Puppet::Configurer::Downloader.expects(:new).with("pluginfacts", plugindest, "psource", "pignore", "myenv").returns downloader
Puppet::Configurer::Downloader.expects(:new).with("plugin", plugindest, "psource", "pignore", "myenv").returns downloader
- downloader.expects(:evaluate).returns []
+ downloader.stubs(:evaluate).returns([])
+ downloader.expects(:evaluate).twice
@pluginhandler.environment = "myenv"
@pluginhandler.download_plugins
diff --git a/spec/unit/configurer_spec.rb b/spec/unit/configurer_spec.rb
index cba1df584..7732bea08 100755
--- a/spec/unit/configurer_spec.rb
+++ b/spec/unit/configurer_spec.rb
@@ -110,6 +110,16 @@ describe Puppet::Configurer do
@agent.run.should == 0
end
+ it "applies a cached catalog when it can't connect to the master" do
+ error = Errno::ECONNREFUSED.new('Connection refused - connect(2)')
+
+ Puppet::Node.indirection.expects(:find).raises(error)
+ Puppet::Resource::Catalog.indirection.expects(:find).with(anything, has_entry(:ignore_cache => true)).raises(error)
+ Puppet::Resource::Catalog.indirection.expects(:find).with(anything, has_entry(:ignore_terminus => true)).returns(@catalog)
+
+ @agent.run.should == 0
+ end
+
it "should initialize a transaction report if one is not provided" do
report = Puppet::Transaction::Report.new("apply")
Puppet::Transaction::Report.expects(:new).returns report
@@ -341,12 +351,12 @@ describe Puppet::Configurer do
@agent.environment.should == "second_env"
end
- it "should clear the thread local caches" do
- Thread.current[:env_module_directories] = false
+ it "should clear the global caches" do
+ $env_module_directories = false
@agent.run
- Thread.current[:env_module_directories].should == nil
+ $env_module_directories.should == nil
end
describe "when not using a REST terminus for catalogs" do
@@ -454,7 +464,7 @@ describe Puppet::Configurer do
it "should write the last run file" do
@configurer.save_last_run_summary(@report)
- FileTest.exists?(Puppet[:lastrunfile]).should be_true
+ Puppet::FileSystem::File.exist?(Puppet[:lastrunfile]).should be_true
end
it "should write the raw summary as yaml" do
@@ -486,7 +496,7 @@ describe Puppet::Configurer do
require 'puppet/util/windows/security'
mode = Puppet::Util::Windows::Security.get_mode(Puppet[:lastrunfile])
else
- mode = File.stat(Puppet[:lastrunfile]).mode
+ mode = Puppet::FileSystem::File.new(Puppet[:lastrunfile]).stat.mode
end
(mode & 0777).should == 0664
end
diff --git a/spec/unit/provider/confine/exists_spec.rb b/spec/unit/confine/exists_spec.rb
index 17fd3f562..87959fe34 100755
--- a/spec/unit/provider/confine/exists_spec.rb
+++ b/spec/unit/confine/exists_spec.rb
@@ -1,20 +1,20 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine/exists'
+require 'puppet/confine/exists'
-describe Puppet::Provider::Confine::Exists do
+describe Puppet::Confine::Exists do
before do
- @confine = Puppet::Provider::Confine::Exists.new("/my/file")
+ @confine = Puppet::Confine::Exists.new("/my/file")
@confine.label = "eh"
end
it "should be named :exists" do
- Puppet::Provider::Confine::Exists.name.should == :exists
+ Puppet::Confine::Exists.name.should == :exists
end
it "should not pass if exists is nil" do
- confine = Puppet::Provider::Confine::Exists.new(nil)
+ confine = Puppet::Confine::Exists.new(nil)
confine.label = ":exists => nil"
confine.expects(:pass?).with(nil)
confine.should_not be_valid
@@ -30,12 +30,12 @@ describe Puppet::Provider::Confine::Exists do
end
it "should return false if the value does not point to a file" do
- FileTest.expects(:exist?).with("/my/file").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("/my/file").returns false
@confine.pass?("/my/file").should be_false
end
it "should return true if the value points to a file" do
- FileTest.expects(:exist?).with("/my/file").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/my/file").returns true
@confine.pass?("/my/file").should be_true
end
@@ -62,11 +62,11 @@ describe Puppet::Provider::Confine::Exists do
end
it "should produce a summary containing all missing files" do
- FileTest.stubs(:exist?).returns true
- FileTest.expects(:exist?).with("/two").returns false
- FileTest.expects(:exist?).with("/four").returns false
+ Puppet::FileSystem::File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/two").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("/four").returns false
- confine = Puppet::Provider::Confine::Exists.new %w{/one /two /three /four}
+ confine = Puppet::Confine::Exists.new %w{/one /two /three /four}
confine.summary.should == %w{/two /four}
end
@@ -75,6 +75,6 @@ describe Puppet::Provider::Confine::Exists do
c2 = mock '2', :summary => %w{two}
c3 = mock '3', :summary => %w{three}
- Puppet::Provider::Confine::Exists.summarize([c1, c2, c3]).should == %w{one two three}
+ Puppet::Confine::Exists.summarize([c1, c2, c3]).should == %w{one two three}
end
end
diff --git a/spec/unit/provider/confine/false_spec.rb b/spec/unit/confine/false_spec.rb
index 91d738c52..44ecd40ed 100755
--- a/spec/unit/provider/confine/false_spec.rb
+++ b/spec/unit/confine/false_spec.rb
@@ -1,22 +1,22 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine/false'
+require 'puppet/confine/false'
-describe Puppet::Provider::Confine::False do
+describe Puppet::Confine::False do
it "should be named :false" do
- Puppet::Provider::Confine::False.name.should == :false
+ Puppet::Confine::False.name.should == :false
end
it "should require a value" do
- lambda { Puppet::Provider::Confine.new }.should raise_error(ArgumentError)
+ lambda { Puppet::Confine.new }.should raise_error(ArgumentError)
end
describe "when testing values" do
- before { @confine = Puppet::Provider::Confine::False.new("foo") }
+ before { @confine = Puppet::Confine::False.new("foo") }
it "should use the 'pass?' method to test validity" do
- @confine = Puppet::Provider::Confine::False.new("foo")
+ @confine = Puppet::Confine::False.new("foo")
@confine.label = "eh"
@confine.expects(:pass?).with("foo")
@confine.valid?
@@ -31,13 +31,13 @@ describe Puppet::Provider::Confine::False do
end
it "should produce a message that a value is true" do
- @confine = Puppet::Provider::Confine::False.new("foo")
+ @confine = Puppet::Confine::False.new("foo")
@confine.message("eh").should be_include("true")
end
end
it "should be able to produce a summary with the number of incorrectly true values" do
- confine = Puppet::Provider::Confine::False.new %w{one two three four}
+ confine = Puppet::Confine::False.new %w{one two three four}
confine.expects(:pass?).times(4).returns(true).returns(false).returns(true).returns(false)
confine.summary.should == 2
end
@@ -47,6 +47,6 @@ describe Puppet::Provider::Confine::False do
c2 = mock '2', :summary => 2
c3 = mock '3', :summary => 3
- Puppet::Provider::Confine::False.summarize([c1, c2, c3]).should == 6
+ Puppet::Confine::False.summarize([c1, c2, c3]).should == 6
end
end
diff --git a/spec/unit/provider/confine/feature_spec.rb b/spec/unit/confine/feature_spec.rb
index b90662235..dad9d9b8b 100755
--- a/spec/unit/provider/confine/feature_spec.rb
+++ b/spec/unit/confine/feature_spec.rb
@@ -1,24 +1,24 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine/feature'
+require 'puppet/confine/feature'
-describe Puppet::Provider::Confine::Feature do
+describe Puppet::Confine::Feature do
it "should be named :feature" do
- Puppet::Provider::Confine::Feature.name.should == :feature
+ Puppet::Confine::Feature.name.should == :feature
end
it "should require a value" do
- lambda { Puppet::Provider::Confine::Feature.new }.should raise_error(ArgumentError)
+ lambda { Puppet::Confine::Feature.new }.should raise_error(ArgumentError)
end
it "should always convert values to an array" do
- Puppet::Provider::Confine::Feature.new("/some/file").values.should be_instance_of(Array)
+ Puppet::Confine::Feature.new("/some/file").values.should be_instance_of(Array)
end
describe "when testing values" do
before do
- @confine = Puppet::Provider::Confine::Feature.new("myfeature")
+ @confine = Puppet::Confine::Feature.new("myfeature")
@confine.label = "eh"
end
@@ -44,14 +44,14 @@ describe Puppet::Provider::Confine::Feature do
it "should summarize multiple instances by returning a flattened array of all missing features" do
confines = []
- confines << Puppet::Provider::Confine::Feature.new(%w{one two})
- confines << Puppet::Provider::Confine::Feature.new(%w{two})
- confines << Puppet::Provider::Confine::Feature.new(%w{three four})
+ confines << Puppet::Confine::Feature.new(%w{one two})
+ confines << Puppet::Confine::Feature.new(%w{two})
+ confines << Puppet::Confine::Feature.new(%w{three four})
features = mock 'feature'
features.stub_everything
Puppet.stubs(:features).returns features
- Puppet::Provider::Confine::Feature.summarize(confines).sort.should == %w{one two three four}.sort
+ Puppet::Confine::Feature.summarize(confines).sort.should == %w{one two three four}.sort
end
end
diff --git a/spec/unit/provider/confine/true_spec.rb b/spec/unit/confine/true_spec.rb
index e869817f0..d7484d59c 100755
--- a/spec/unit/provider/confine/true_spec.rb
+++ b/spec/unit/confine/true_spec.rb
@@ -1,20 +1,20 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine/true'
+require 'puppet/confine/true'
-describe Puppet::Provider::Confine::True do
+describe Puppet::Confine::True do
it "should be named :true" do
- Puppet::Provider::Confine::True.name.should == :true
+ Puppet::Confine::True.name.should == :true
end
it "should require a value" do
- lambda { Puppet::Provider::Confine::True.new }.should raise_error(ArgumentError)
+ lambda { Puppet::Confine::True.new }.should raise_error(ArgumentError)
end
describe "when testing values" do
before do
- @confine = Puppet::Provider::Confine::True.new("foo")
+ @confine = Puppet::Confine::True.new("foo")
@confine.label = "eh"
end
@@ -37,7 +37,7 @@ describe Puppet::Provider::Confine::True do
end
it "should produce the number of false values when asked for a summary" do
- @confine = Puppet::Provider::Confine::True.new %w{one two three four}
+ @confine = Puppet::Confine::True.new %w{one two three four}
@confine.expects(:pass?).times(4).returns(true).returns(false).returns(true).returns(false)
@confine.summary.should == 2
end
@@ -47,6 +47,6 @@ describe Puppet::Provider::Confine::True do
c2 = mock '2', :summary => 2
c3 = mock '3', :summary => 3
- Puppet::Provider::Confine::True.summarize([c1, c2, c3]).should == 6
+ Puppet::Confine::True.summarize([c1, c2, c3]).should == 6
end
end
diff --git a/spec/unit/provider/confine/variable_spec.rb b/spec/unit/confine/variable_spec.rb
index d06705c6f..be45e3bb1 100755
--- a/spec/unit/provider/confine/variable_spec.rb
+++ b/spec/unit/confine/variable_spec.rb
@@ -1,28 +1,28 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine/variable'
+require 'puppet/confine/variable'
-describe Puppet::Provider::Confine::Variable do
+describe Puppet::Confine::Variable do
it "should be named :variable" do
- Puppet::Provider::Confine::Variable.name.should == :variable
+ Puppet::Confine::Variable.name.should == :variable
end
it "should require a value" do
- lambda { Puppet::Provider::Confine::Variable.new }.should raise_error(ArgumentError)
+ lambda { Puppet::Confine::Variable.new }.should raise_error(ArgumentError)
end
it "should always convert values to an array" do
- Puppet::Provider::Confine::Variable.new("/some/file").values.should be_instance_of(Array)
+ Puppet::Confine::Variable.new("/some/file").values.should be_instance_of(Array)
end
it "should have an accessor for its name" do
- Puppet::Provider::Confine::Variable.new(:bar).should respond_to(:name)
+ Puppet::Confine::Variable.new(:bar).should respond_to(:name)
end
describe "when testing values" do
before do
- @confine = Puppet::Provider::Confine::Variable.new("foo")
+ @confine = Puppet::Confine::Variable.new("foo")
@confine.name = :myvar
end
@@ -63,7 +63,7 @@ describe Puppet::Provider::Confine::Variable do
end
it "should produce a message that the fact value is not correct" do
- @confine = Puppet::Provider::Confine::Variable.new(%w{bar bee})
+ @confine = Puppet::Confine::Variable.new(%w{bar bee})
@confine.name = "eh"
message = @confine.message("value")
message.should be_include("facter")
@@ -71,7 +71,7 @@ describe Puppet::Provider::Confine::Variable do
end
it "should be valid if the test value matches any of the provided values" do
- @confine = Puppet::Provider::Confine::Variable.new(%w{bar bee})
+ @confine = Puppet::Confine::Variable.new(%w{bar bee})
@confine.expects(:test_value).returns "bee"
@confine.should be_valid
end
@@ -79,28 +79,28 @@ describe Puppet::Provider::Confine::Variable do
describe "when summarizing multiple instances" do
it "should return a hash of failing variables and their values" do
- c1 = Puppet::Provider::Confine::Variable.new("one")
+ c1 = Puppet::Confine::Variable.new("one")
c1.name = "uno"
c1.expects(:valid?).returns false
- c2 = Puppet::Provider::Confine::Variable.new("two")
+ c2 = Puppet::Confine::Variable.new("two")
c2.name = "dos"
c2.expects(:valid?).returns true
- c3 = Puppet::Provider::Confine::Variable.new("three")
+ c3 = Puppet::Confine::Variable.new("three")
c3.name = "tres"
c3.expects(:valid?).returns false
- Puppet::Provider::Confine::Variable.summarize([c1, c2, c3]).should == {"uno" => %w{one}, "tres" => %w{three}}
+ Puppet::Confine::Variable.summarize([c1, c2, c3]).should == {"uno" => %w{one}, "tres" => %w{three}}
end
it "should combine the values of multiple confines with the same fact" do
- c1 = Puppet::Provider::Confine::Variable.new("one")
+ c1 = Puppet::Confine::Variable.new("one")
c1.name = "uno"
c1.expects(:valid?).returns false
- c2 = Puppet::Provider::Confine::Variable.new("two")
+ c2 = Puppet::Confine::Variable.new("two")
c2.name = "uno"
c2.expects(:valid?).returns false
- Puppet::Provider::Confine::Variable.summarize([c1, c2]).should == {"uno" => %w{one two}}
+ Puppet::Confine::Variable.summarize([c1, c2]).should == {"uno" => %w{one two}}
end
end
end
diff --git a/spec/unit/provider/confine_collection_spec.rb b/spec/unit/confine_collection_spec.rb
index 31a778fd7..958f69197 100755
--- a/spec/unit/provider/confine_collection_spec.rb
+++ b/spec/unit/confine_collection_spec.rb
@@ -1,72 +1,72 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine_collection'
+require 'puppet/confine_collection'
-describe Puppet::Provider::ConfineCollection do
+describe Puppet::ConfineCollection do
it "should be able to add confines" do
- Puppet::Provider::ConfineCollection.new("label").should respond_to(:confine)
+ Puppet::ConfineCollection.new("label").should respond_to(:confine)
end
it "should require a label at initialization" do
- lambda { Puppet::Provider::ConfineCollection.new }.should raise_error(ArgumentError)
+ lambda { Puppet::ConfineCollection.new }.should raise_error(ArgumentError)
end
it "should make its label available" do
- Puppet::Provider::ConfineCollection.new("mylabel").label.should == "mylabel"
+ Puppet::ConfineCollection.new("mylabel").label.should == "mylabel"
end
describe "when creating confine instances" do
it "should create an instance of the named test with the provided values" do
test_class = mock 'test_class'
test_class.expects(:new).with(%w{my values}).returns(stub('confine', :label= => nil))
- Puppet::Provider::Confine.expects(:test).with(:foo).returns test_class
+ Puppet::Confine.expects(:test).with(:foo).returns test_class
- Puppet::Provider::ConfineCollection.new("label").confine :foo => %w{my values}
+ Puppet::ConfineCollection.new("label").confine :foo => %w{my values}
end
it "should copy its label to the confine instance" do
confine = mock 'confine'
test_class = mock 'test_class'
test_class.expects(:new).returns confine
- Puppet::Provider::Confine.expects(:test).returns test_class
+ Puppet::Confine.expects(:test).returns test_class
confine.expects(:label=).with("label")
- Puppet::Provider::ConfineCollection.new("label").confine :foo => %w{my values}
+ Puppet::ConfineCollection.new("label").confine :foo => %w{my values}
end
describe "and the test cannot be found" do
it "should create a Facter test with the provided values and set the name to the test name" do
- confine = Puppet::Provider::Confine.test(:variable).new(%w{my values})
+ confine = Puppet::Confine.test(:variable).new(%w{my values})
confine.expects(:name=).with(:foo)
confine.class.expects(:new).with(%w{my values}).returns confine
- Puppet::Provider::ConfineCollection.new("label").confine(:foo => %w{my values})
+ Puppet::ConfineCollection.new("label").confine(:foo => %w{my values})
end
end
describe "and the 'for_binary' option was provided" do
it "should mark the test as a binary confine" do
- confine = Puppet::Provider::Confine.test(:exists).new(:bar)
+ confine = Puppet::Confine.test(:exists).new(:bar)
confine.expects(:for_binary=).with true
- Puppet::Provider::Confine.test(:exists).expects(:new).with(:bar).returns confine
- Puppet::Provider::ConfineCollection.new("label").confine :exists => :bar, :for_binary => true
+ Puppet::Confine.test(:exists).expects(:new).with(:bar).returns confine
+ Puppet::ConfineCollection.new("label").confine :exists => :bar, :for_binary => true
end
end
end
it "should be valid if no confines are present" do
- Puppet::Provider::ConfineCollection.new("label").should be_valid
+ Puppet::ConfineCollection.new("label").should be_valid
end
it "should be valid if all confines pass" do
c1 = stub 'c1', :valid? => true, :label= => nil
c2 = stub 'c2', :valid? => true, :label= => nil
- Puppet::Provider::Confine.test(:true).expects(:new).returns(c1)
- Puppet::Provider::Confine.test(:false).expects(:new).returns(c2)
+ Puppet::Confine.test(:true).expects(:new).returns(c1)
+ Puppet::Confine.test(:false).expects(:new).returns(c2)
- confiner = Puppet::Provider::ConfineCollection.new("label")
+ confiner = Puppet::ConfineCollection.new("label")
confiner.confine :true => :bar, :false => :bee
confiner.should be_valid
@@ -76,10 +76,10 @@ describe Puppet::Provider::ConfineCollection do
c1 = stub 'c1', :valid? => true, :label= => nil
c2 = stub 'c2', :valid? => false, :label= => nil
- Puppet::Provider::Confine.test(:true).expects(:new).returns(c1)
- Puppet::Provider::Confine.test(:false).expects(:new).returns(c2)
+ Puppet::Confine.test(:true).expects(:new).returns(c1)
+ Puppet::Confine.test(:false).expects(:new).returns(c2)
- confiner = Puppet::Provider::ConfineCollection.new("label")
+ confiner = Puppet::ConfineCollection.new("label")
confiner.confine :true => :bar, :false => :bee
confiner.should_not be_valid
@@ -87,7 +87,7 @@ describe Puppet::Provider::ConfineCollection do
describe "when providing a summary" do
before do
- @confiner = Puppet::Provider::ConfineCollection.new("label")
+ @confiner = Puppet::ConfineCollection.new("label")
end
it "should return a hash" do
@@ -100,32 +100,32 @@ describe Puppet::Provider::ConfineCollection do
it "should add each test type's summary to the hash" do
@confiner.confine :true => :bar, :false => :bee
- Puppet::Provider::Confine.test(:true).expects(:summarize).returns :tsumm
- Puppet::Provider::Confine.test(:false).expects(:summarize).returns :fsumm
+ Puppet::Confine.test(:true).expects(:summarize).returns :tsumm
+ Puppet::Confine.test(:false).expects(:summarize).returns :fsumm
@confiner.summary.should == {:true => :tsumm, :false => :fsumm}
end
it "should not include tests that return 0" do
@confiner.confine :true => :bar, :false => :bee
- Puppet::Provider::Confine.test(:true).expects(:summarize).returns 0
- Puppet::Provider::Confine.test(:false).expects(:summarize).returns :fsumm
+ Puppet::Confine.test(:true).expects(:summarize).returns 0
+ Puppet::Confine.test(:false).expects(:summarize).returns :fsumm
@confiner.summary.should == {:false => :fsumm}
end
it "should not include tests that return empty arrays" do
@confiner.confine :true => :bar, :false => :bee
- Puppet::Provider::Confine.test(:true).expects(:summarize).returns []
- Puppet::Provider::Confine.test(:false).expects(:summarize).returns :fsumm
+ Puppet::Confine.test(:true).expects(:summarize).returns []
+ Puppet::Confine.test(:false).expects(:summarize).returns :fsumm
@confiner.summary.should == {:false => :fsumm}
end
it "should not include tests that return empty hashes" do
@confiner.confine :true => :bar, :false => :bee
- Puppet::Provider::Confine.test(:true).expects(:summarize).returns({})
- Puppet::Provider::Confine.test(:false).expects(:summarize).returns :fsumm
+ Puppet::Confine.test(:true).expects(:summarize).returns({})
+ Puppet::Confine.test(:false).expects(:summarize).returns :fsumm
@confiner.summary.should == {:false => :fsumm}
end
diff --git a/spec/unit/provider/confine_spec.rb b/spec/unit/confine_spec.rb
index 38dfd8c3f..06c10abd7 100755
--- a/spec/unit/provider/confine_spec.rb
+++ b/spec/unit/confine_spec.rb
@@ -1,40 +1,40 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confine'
+require 'puppet/confine'
-describe Puppet::Provider::Confine do
+describe Puppet::Confine do
it "should require a value" do
- lambda { Puppet::Provider::Confine.new }.should raise_error(ArgumentError)
+ lambda { Puppet::Confine.new }.should raise_error(ArgumentError)
end
it "should always convert values to an array" do
- Puppet::Provider::Confine.new("/some/file").values.should be_instance_of(Array)
+ Puppet::Confine.new("/some/file").values.should be_instance_of(Array)
end
it "should have a 'true' test" do
- Puppet::Provider::Confine.test(:true).should be_instance_of(Class)
+ Puppet::Confine.test(:true).should be_instance_of(Class)
end
it "should have a 'false' test" do
- Puppet::Provider::Confine.test(:false).should be_instance_of(Class)
+ Puppet::Confine.test(:false).should be_instance_of(Class)
end
it "should have a 'feature' test" do
- Puppet::Provider::Confine.test(:feature).should be_instance_of(Class)
+ Puppet::Confine.test(:feature).should be_instance_of(Class)
end
it "should have an 'exists' test" do
- Puppet::Provider::Confine.test(:exists).should be_instance_of(Class)
+ Puppet::Confine.test(:exists).should be_instance_of(Class)
end
it "should have a 'variable' test" do
- Puppet::Provider::Confine.test(:variable).should be_instance_of(Class)
+ Puppet::Confine.test(:variable).should be_instance_of(Class)
end
describe "when testing all values" do
before do
- @confine = Puppet::Provider::Confine.new(%w{a b c})
+ @confine = Puppet::Confine.new(%w{a b c})
@confine.label = "foo"
end
@@ -64,7 +64,7 @@ describe Puppet::Provider::Confine do
end
describe "when testing the result of the values" do
- before { @confine = Puppet::Provider::Confine.new(%w{a b c d}) }
+ before { @confine = Puppet::Confine.new(%w{a b c d}) }
it "should return an array with the result of the test for each value" do
@confine.stubs(:pass?).returns true
diff --git a/spec/unit/provider/confiner_spec.rb b/spec/unit/confiner_spec.rb
index 2afdd71a3..2d71054fe 100755
--- a/spec/unit/provider/confiner_spec.rb
+++ b/spec/unit/confiner_spec.rb
@@ -1,12 +1,12 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'puppet/provider/confiner'
+require 'puppet/confiner'
-describe Puppet::Provider::Confiner do
+describe Puppet::Confiner do
before do
@object = Object.new
- @object.extend(Puppet::Provider::Confiner)
+ @object.extend(Puppet::Confiner)
end
it "should have a method for defining confines" do
@@ -29,7 +29,7 @@ describe Puppet::Provider::Confiner do
end
it "should create a new confine collection if one does not exist" do
- Puppet::Provider::ConfineCollection.expects(:new).with("mylabel").returns "mycoll"
+ Puppet::ConfineCollection.expects(:new).with("mylabel").returns "mycoll"
@object.expects(:to_s).returns "mylabel"
@object.confine_collection.should == "mycoll"
end
diff --git a/spec/unit/face/parser_spec.rb b/spec/unit/face/parser_spec.rb
new file mode 100644
index 000000000..a517ae641
--- /dev/null
+++ b/spec/unit/face/parser_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+require 'puppet_spec/files'
+
+require 'puppet/face'
+
+describe Puppet::Face[:parser, :current] do
+ include PuppetSpec::Files
+
+ let(:parser) { Puppet::Face[:parser, :current] }
+
+ it "validates the configured site manifest when no files are given" do
+ Puppet[:manifest] = file_containing('site.pp', "{ invalid =>")
+ from_an_interactive_terminal
+
+ expect { parser.validate() }.to exit_with(1)
+ end
+
+ it "validates the given file" do
+ manifest = file_containing('site.pp', "{ invalid =>")
+ from_an_interactive_terminal
+
+ expect { parser.validate(manifest) }.to exit_with(1)
+ end
+
+ it "validates the contents of STDIN when no files given and STDIN is not a tty" do
+ from_a_piped_input_of("{ invalid =>")
+
+ expect { parser.validate() }.to exit_with(1)
+ end
+
+ it "runs error free when there are no validation errors" do
+ manifest = file_containing('site.pp', "notify { valid: }")
+ from_an_interactive_terminal
+
+ parser.validate(manifest)
+ end
+
+ it "reports missing files" do
+ from_an_interactive_terminal
+
+ expect do
+ parser.validate("missing.pp")
+ end.to raise_error(Puppet::Error, /One or more file\(s\) specified did not exist.*missing\.pp/m)
+ end
+
+ def from_an_interactive_terminal
+ STDIN.stubs(:tty?).returns(true)
+ end
+
+ def from_a_piped_input_of(contents)
+ STDIN.stubs(:tty?).returns(false)
+ STDIN.stubs(:read).returns(contents)
+ end
+end
diff --git a/spec/unit/file_bucket/dipper_spec.rb b/spec/unit/file_bucket/dipper_spec.rb
index 397cb9219..83e914851 100755
--- a/spec/unit/file_bucket/dipper_spec.rb
+++ b/spec/unit/file_bucket/dipper_spec.rb
@@ -45,7 +45,7 @@ describe Puppet::FileBucket::Dipper do
Digest::MD5.hexdigest("my\r\ncontents").should == checksum
@dipper.backup(file).should == checksum
- File.exists?("#{file_bucket}/f/0/d/7/d/4/e/4/f0d7d4e480ad698ed56aeec8b6bd6dea/contents").should == true
+ Puppet::FileSystem::File.exist?("#{file_bucket}/f/0/d/7/d/4/e/4/f0d7d4e480ad698ed56aeec8b6bd6dea/contents").should == true
end
it "should not backup a file that is already in the bucket" do
@@ -123,7 +123,7 @@ describe Puppet::FileBucket::Dipper do
klass.any_instance.expects(:find).with { |r| request = r }.returns(Puppet::FileBucket::File.new(contents))
dipper.restore(dest, md5).should == md5
- Digest::MD5.hexdigest(IO.binread(dest)).should == md5
+ Digest::MD5.hexdigest(Puppet::FileSystem::File.new(dest).binread).should == md5
request.key.should == "md5/#{md5}"
request.server.should == server
diff --git a/spec/unit/file_serving/base_spec.rb b/spec/unit/file_serving/base_spec.rb
index a172830e8..65168d3a3 100755
--- a/spec/unit/file_serving/base_spec.rb
+++ b/spec/unit/file_serving/base_spec.rb
@@ -42,12 +42,12 @@ describe Puppet::FileServing::Base do
end
it "should allow specification of a path" do
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet::FileServing::Base.new(path, :path => file).path.should == file
end
it "should allow specification of a relative path" do
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet::FileServing::Base.new(path, :relative_path => "my/file").relative_path.should == "my/file"
end
@@ -56,19 +56,22 @@ describe Puppet::FileServing::Base do
end
it "should correctly indicate if the file is present" do
- File.expects(:lstat).with(file).returns(mock("stat"))
+ mock_file = mock(file, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(file).returns mock_file
Puppet::FileServing::Base.new(file).exist?.should be_true
end
it "should correctly indicate if the file is absent" do
- File.expects(:lstat).with(file).raises RuntimeError
+ mock_file = mock(file)
+ Puppet::FileSystem::File.expects(:new).with(file).returns mock_file
+ mock_file.expects(:lstat).raises RuntimeError
Puppet::FileServing::Base.new(file).exist?.should be_false
end
describe "when setting the relative path" do
it "should require that the relative path be unqualified" do
@file = Puppet::FileServing::Base.new(path)
- FileTest.stubs(:exists?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
proc { @file.relative_path = File.expand_path("/qualified/file") }.should raise_error(ArgumentError)
end
end
@@ -102,27 +105,47 @@ describe Puppet::FileServing::Base do
end
end
+ describe "when handling a UNC file path on Windows" do
+ let(:path) { '//server/share/filename' }
+ let(:file) { Puppet::FileServing::Base.new(path) }
+
+ it "should preserve double slashes at the beginning of the path" do
+ Puppet.features.stubs(:microsoft_windows?).returns(true)
+ file.full_path.should == path
+ end
+
+ it "should strip double slashes not at the beginning of the path" do
+ Puppet.features.stubs(:microsoft_windows?).returns(true)
+ file = Puppet::FileServing::Base.new('//server//share//filename')
+ file.full_path.should == path
+ end
+ end
+
+
describe "when stat'ing files" do
let(:path) { File.expand_path('/this/file') }
let(:file) { Puppet::FileServing::Base.new(path) }
+ let(:stat) { stub('stat', :ftype => 'file' ) }
+ let(:stubbed_file) { stub(path, :stat => stat, :lstat => stat)}
it "should stat the file's full path" do
- File.expects(:lstat).with(path).returns stub("stat", :ftype => "file")
+ Puppet::FileSystem::File.expects(:new).with(path).returns stubbed_file
file.stat
end
it "should fail if the file does not exist" do
- File.expects(:lstat).with(path).raises(Errno::ENOENT)
+ Puppet::FileSystem::File.expects(:new).with(path).returns stubbed_file
+ stubbed_file.expects(:lstat).raises(Errno::ENOENT)
proc { file.stat }.should raise_error(Errno::ENOENT)
end
it "should use :lstat if :links is set to :manage" do
- File.expects(:lstat).with(path).returns stub("stat", :ftype => "file")
+ Puppet::FileSystem::File.expects(:new).with(path).returns stubbed_file
file.stat
end
it "should use :stat if :links is set to :follow" do
- File.expects(:stat).with(path).returns stub("stat", :ftype => "file")
+ Puppet::FileSystem::File.expects(:new).with(path).returns stubbed_file
file.links = :follow
file.stat
end
diff --git a/spec/unit/file_serving/configuration_spec.rb b/spec/unit/file_serving/configuration_spec.rb
index 2552cd808..b6999e086 100755
--- a/spec/unit/file_serving/configuration_spec.rb
+++ b/spec/unit/file_serving/configuration_spec.rb
@@ -27,12 +27,12 @@ describe Puppet::FileServing::Configuration do
describe "when initializing" do
it "should work without a configuration file" do
- FileTest.stubs(:exists?).with(@path).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).with(@path).returns(false)
expect { Puppet::FileServing::Configuration.configuration }.to_not raise_error
end
it "should parse the configuration file if present" do
- FileTest.stubs(:exists?).with(@path).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(@path).returns(true)
@parser = mock 'parser'
@parser.expects(:parse).returns({})
Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
@@ -47,7 +47,7 @@ describe Puppet::FileServing::Configuration do
describe "when parsing the configuration file" do
before do
- FileTest.stubs(:exists?).with(@path).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(@path).returns(true)
@parser = mock 'parser'
Puppet::FileServing::Configuration::Parser.stubs(:new).returns(@parser)
end
@@ -84,14 +84,14 @@ describe Puppet::FileServing::Configuration do
end
it "should add modules and plugins mounts even if the file does not exist" do
- FileTest.expects(:exists?).returns false # the file doesn't exist
+ Puppet::FileSystem::File.expects(:exist?).returns false # the file doesn't exist
config = Puppet::FileServing::Configuration.configuration
config.mounted?("modules").should be_true
config.mounted?("plugins").should be_true
end
it "should allow all access to modules and plugins if no fileserver.conf exists" do
- FileTest.expects(:exists?).returns false # the file doesn't exist
+ Puppet::FileSystem::File.expects(:exist?).returns false # the file doesn't exist
modules = stub 'modules', :empty? => true
Puppet::FileServing::Mount::Modules.stubs(:new).returns(modules)
modules.expects(:allow).with('*')
@@ -104,7 +104,7 @@ describe Puppet::FileServing::Configuration do
end
it "should not allow access from all to modules and plugins if the fileserver.conf provided some rules" do
- FileTest.expects(:exists?).returns false # the file doesn't exist
+ Puppet::FileSystem::File.expects(:exist?).returns false # the file doesn't exist
modules = stub 'modules', :empty? => false
Puppet::FileServing::Mount::Modules.stubs(:new).returns(modules)
@@ -119,7 +119,7 @@ describe Puppet::FileServing::Configuration do
it "should add modules and plugins mounts even if they are not returned by the parser" do
@parser.expects(:parse).returns("one" => mock("mount"))
- FileTest.expects(:exists?).returns true # the file doesn't exist
+ Puppet::FileSystem::File.expects(:exist?).returns true # the file doesn't exist
config = Puppet::FileServing::Configuration.configuration
config.mounted?("modules").should be_true
config.mounted?("plugins").should be_true
diff --git a/spec/unit/file_serving/content_spec.rb b/spec/unit/file_serving/content_spec.rb
index 2169c9b57..2cb159f0a 100755
--- a/spec/unit/file_serving/content_spec.rb
+++ b/spec/unit/file_serving/content_spec.rb
@@ -26,7 +26,8 @@ describe Puppet::FileServing::Content do
content = Puppet::FileServing::Content.new(path)
result = "foo"
- File.stubs(:lstat).returns(stub("stat", :ftype => "file"))
+ stub_file = stub(path, :lstat => stub('stat', :ftype => "file"))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
File.expects(:read).with(path).never
content.collect
@@ -37,7 +38,8 @@ describe Puppet::FileServing::Content do
content = Puppet::FileServing::Content.new(path)
result = "foo"
- File.stubs(:lstat).returns(stub("stat", :ftype => "directory"))
+ stub_file = stub(path, :lstat => stub('stat', :ftype => "directory"))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
File.expects(:read).with(path).never
content.collect
@@ -83,7 +85,8 @@ describe Puppet::FileServing::Content, "when returning the contents" do
it "should fail if the file is a symlink and links are set to :manage" do
content.links = :manage
- File.expects(:lstat).with(path).returns stub("stat", :ftype => "symlink")
+ stub_file = stub(path, :lstat => stub("stat", :ftype => "symlink"))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
proc { content.content }.should raise_error(ArgumentError)
end
@@ -97,14 +100,16 @@ describe Puppet::FileServing::Content, "when returning the contents" do
end
it "should return the contents of the path if the file exists" do
- File.expects(:stat).with(path).returns stub("stat", :ftype => "file")
- IO.expects(:binread).with(path).returns(:mycontent)
+ mocked_file = mock(path, :stat => stub('stat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(path).twice.returns(mocked_file)
+ mocked_file.expects(:binread).returns(:mycontent)
content.content.should == :mycontent
end
it "should cache the returned contents" do
- File.expects(:stat).with(path).returns stub("stat", :ftype => "file")
- IO.expects(:binread).with(path).returns(:mycontent)
+ mocked_file = mock(path, :stat => stub('stat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(path).twice.returns(mocked_file)
+ mocked_file.expects(:binread).returns(:mycontent)
content.content
# The second run would throw a failure if the content weren't being cached.
content.content
diff --git a/spec/unit/file_serving/fileset_spec.rb b/spec/unit/file_serving/fileset_spec.rb
index f6a661843..0e61a2a59 100755
--- a/spec/unit/file_serving/fileset_spec.rb
+++ b/spec/unit/file_serving/fileset_spec.rb
@@ -18,49 +18,58 @@ describe Puppet::FileServing::Fileset do
it "removes a trailing file path separator" do
path_with_separator = "#{somefile}#{File::SEPARATOR}"
- File.stubs(:lstat).with(somefile).returns stub('stat')
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
fileset = Puppet::FileServing::Fileset.new(path_with_separator)
fileset.path.should == somefile
end
it "can be created from the root directory" do
path = File.expand_path(File::SEPARATOR)
- File.stubs(:lstat).with(path).returns stub('stat')
+ stub_file = stub(path, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
fileset = Puppet::FileServing::Fileset.new(path)
fileset.path.should == path
end
it "fails if its path does not exist" do
- File.expects(:lstat).with(somefile).raises(Errno::ENOENT)
+ mock_file = mock(somefile)
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns mock_file
+ mock_file.expects(:lstat).raises(Errno::ENOENT)
expect { Puppet::FileServing::Fileset.new(somefile) }.to raise_error(ArgumentError, "Fileset paths must exist")
end
it "accepts a 'recurse' option" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
set = Puppet::FileServing::Fileset.new(somefile, :recurse => true)
set.recurse.should be_true
end
it "accepts a 'recurselimit' option" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
set = Puppet::FileServing::Fileset.new(somefile, :recurselimit => 3)
set.recurselimit.should == 3
end
it "accepts an 'ignore' option" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
set = Puppet::FileServing::Fileset.new(somefile, :ignore => ".svn")
set.ignore.should == [".svn"]
end
it "accepts a 'links' option" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
set = Puppet::FileServing::Fileset.new(somefile, :links => :manage)
set.links.should == :manage
end
it "accepts a 'checksum_type' option" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
set = Puppet::FileServing::Fileset.new(somefile, :checksum_type => :test)
set.checksum_type.should == :test
end
@@ -70,30 +79,35 @@ describe Puppet::FileServing::Fileset do
end
it "defaults to 'false' for recurse" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
Puppet::FileServing::Fileset.new(somefile).recurse.should == false
end
it "defaults to :infinite for recurselimit" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
Puppet::FileServing::Fileset.new(somefile).recurselimit.should == :infinite
end
it "defaults to an empty ignore list" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
Puppet::FileServing::Fileset.new(somefile).ignore.should == []
end
it "defaults to :manage for links" do
- File.expects(:lstat).with(somefile).returns stub("stat")
+ stub_file = stub(somefile, :lstat => stub('stat'))
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
Puppet::FileServing::Fileset.new(somefile).links.should == :manage
end
describe "using an indirector request" do
let(:values) { { :links => :manage, :ignore => %w{a b}, :recurse => true, :recurselimit => 1234 } }
+ let(:stub_file) { stub(somefile, :lstat => stub('stat')) }
before :each do
- File.stubs(:lstat).returns stub("stat")
+ Puppet::FileSystem::File.expects(:new).with(somefile).returns stub_file
end
[:recurse, :recurselimit, :ignore, :links].each do |option|
@@ -130,7 +144,8 @@ describe Puppet::FileServing::Fileset do
context "when recursing" do
before do
@path = make_absolute("/my/path")
- File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+ @stub_file = stub(@path, :lstat => stub('stat', :directory? => true))
+ Puppet::FileSystem::File.stubs(:new).with(@path).returns @stub_file
@fileset = Puppet::FileServing::Fileset.new(@path)
@dirstat = stub 'dirstat', :directory? => true
@@ -138,7 +153,7 @@ describe Puppet::FileServing::Fileset do
end
def mock_dir_structure(path, stat_method = :lstat)
- File.stubs(stat_method).with(path).returns(@dirstat)
+ @stub_file.stubs(stat_method).returns(@dirstat)
Dir.stubs(:entries).with(path).returns(%w{one two .svn CVS})
# Keep track of the files we're stubbing.
@@ -147,11 +162,14 @@ describe Puppet::FileServing::Fileset do
%w{one two .svn CVS}.each do |subdir|
@files << subdir # relative path
subpath = File.join(path, subdir)
- File.stubs(stat_method).with(subpath).returns(@dirstat)
+ stub_subpath = stub(subpath, stat_method => @dirstat)
+ Puppet::FileSystem::File.stubs(:new).with(subpath).returns stub_subpath
Dir.stubs(:entries).with(subpath).returns(%w{.svn CVS file1 file2})
%w{file1 file2 .svn CVS}.each do |file|
@files << File.join(subdir, file) # relative path
- File.stubs(stat_method).with(File.join(subpath, file)).returns(@filestat)
+ subfile_path = File.join(subpath, file)
+ stub_subfile_path = stub(subfile_path, stat_method => @filestat)
+ Puppet::FileSystem::File.stubs(:new).with(subfile_path).returns stub_subfile_path
end
end
end
@@ -165,8 +183,10 @@ describe Puppet::FileServing::Fileset do
MockDirectory = Struct.new(:name, :entries) do
def mock(base_path)
+ extend Mocha::API
path = File.join(base_path, name)
- File.stubs(:lstat).with(path).returns(MockStat.new(path, true))
+ stub_dir = stub(path, :lstat => MockStat.new(path, true))
+ Puppet::FileSystem::File.stubs(:new).with(path).returns stub_dir
Dir.stubs(:entries).with(path).returns(['.', '..'] + entries.map(&:name))
entries.each do |entry|
entry.mock(path)
@@ -176,8 +196,10 @@ describe Puppet::FileServing::Fileset do
MockFile = Struct.new(:name) do
def mock(base_path)
+ extend Mocha::API
path = File.join(base_path, name)
- File.stubs(:lstat).with(path).returns(MockStat.new(path, false))
+ stub_file = stub(path, :lstat => MockStat.new(path, false))
+ Puppet::FileSystem::File.stubs(:new).with(path).returns stub_file
end
end
@@ -239,14 +261,14 @@ describe Puppet::FileServing::Fileset do
@fileset.files.find { |file| file.include?(".svn") or file.include?("CVS") }.should be_nil
end
- it "uses File.stat if :links is set to :follow" do
+ it "uses Puppet::FileSystem::File#stat if :links is set to :follow" do
mock_dir_structure(@path, :stat)
@fileset.recurse = true
@fileset.links = :follow
@fileset.files.sort.should == @files.sort
end
- it "uses File.lstat if :links is set to :manage" do
+ it "uses Puppet::FileSystem::File#lstat if :links is set to :manage" do
mock_dir_structure(@path, :lstat)
@fileset.recurse = true
@fileset.links = :manage
@@ -255,7 +277,9 @@ describe Puppet::FileServing::Fileset do
it "works when paths have regexp significant characters" do
@path = make_absolute("/my/path/rV1x2DafFr0R6tGG+1bbk++++TM")
- File.expects(:lstat).with(@path).returns stub("stat", :directory? => true)
+ stat = stub('dir_stat', :directory? => true)
+ stub_file = stub(@path, :stat => stat, :lstat => stat)
+ Puppet::FileSystem::File.expects(:new).with(@path).twice.returns stub_file
@fileset = Puppet::FileServing::Fileset.new(@path)
mock_dir_structure(@path)
@fileset.recurse = true
@@ -267,9 +291,13 @@ describe Puppet::FileServing::Fileset do
path = make_absolute("/my/path")
stat = stub 'stat', :directory? => true
- File.expects(:lstat).with(path).returns(stat)
- File.expects(:stat).with(path).returns(stat)
- File.expects(:stat).with(File.join(path, "mylink")).raises(Errno::ENOENT)
+ mock_file = mock(path, :lstat => stat, :stat => stat)
+ Puppet::FileSystem::File.expects(:new).with(path).twice.returns mock_file
+
+ link_path = File.join(path, "mylink")
+ mock_link = mock(link_path)
+ Puppet::FileSystem::File.expects(:new).with(link_path).returns mock_link
+ mock_link.expects(:stat).raises(Errno::ENOENT)
Dir.stubs(:entries).with(path).returns(["mylink"])
@@ -284,10 +312,12 @@ describe Puppet::FileServing::Fileset do
context "when merging other filesets" do
before do
@paths = [make_absolute("/first/path"), make_absolute("/second/path"), make_absolute("/third/path")]
- File.stubs(:lstat).returns stub("stat", :directory? => false)
+ stub_file = stub(:lstat => stub('stat', :directory? => false))
+ Puppet::FileSystem::File.stubs(:new).returns stub_file
@filesets = @paths.collect do |path|
- File.stubs(:lstat).with(path).returns stub("stat", :directory? => true)
+ stub_dir = stub(path, :lstat => stub('stat', :directory? => true))
+ Puppet::FileSystem::File.stubs(:new).with(path).returns stub_dir
Puppet::FileServing::Fileset.new(path, :recurse => true)
end
diff --git a/spec/unit/file_serving/metadata_spec.rb b/spec/unit/file_serving/metadata_spec.rb
index 28d48e4ec..8b74d4b7e 100755
--- a/spec/unit/file_serving/metadata_spec.rb
+++ b/spec/unit/file_serving/metadata_spec.rb
@@ -3,6 +3,21 @@ require 'spec_helper'
require 'puppet/file_serving/metadata'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ FILE_METADATA_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__), '../../../api/schemas/file_metadata.json')))
+
+ describe "catalog schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, FILE_METADATA_SCHEMA)
+ end
+ end
+
+ def validate_json_for_file_metadata(file_metadata)
+ JSON::Validator.validate!(FILE_METADATA_SCHEMA, file_metadata.to_pson)
+ end
+end
+
describe Puppet::FileServing::Metadata do
let(:foobar) { File.expand_path('/foo/bar') }
@@ -84,7 +99,6 @@ describe Puppet::FileServing::Metadata do
it "should pass the checksum in the hash verbatim as the checksum's value" do
metadata.to_pson_data_hash['data']['checksum']['value'].should == metadata.checksum
end
-
end
end
@@ -139,6 +153,10 @@ describe Puppet::FileServing::Metadata do
metadata.checksum.should == "{mtime}#{@time}"
end
end
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ validate_json_for_file_metadata(metadata)
+ end
end
describe "when managing directories" do
@@ -160,25 +178,45 @@ describe Puppet::FileServing::Metadata do
metadata.collect
metadata.checksum.should == "{ctime}#{time}"
end
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ metadata.collect
+ validate_json_for_file_metadata(metadata)
+ end
end
+ end
+ end
- describe "when managing links", :unless => Puppet.features.microsoft_windows? do
+ shared_examples_for "metadata collector symlinks" do
+
+ let(:metadata) do
+ data = described_class.new(path)
+ data.collect
+ data
+ end
+
+ describe "when collecting attributes" do
+ describe "when managing links" do
# 'path' is a link that points to 'target'
let(:path) { tmpfile('file_serving_metadata_link') }
let(:target) { tmpfile('file_serving_metadata_target') }
let(:checksum) { Digest::MD5.hexdigest("some content\n") }
- let(:fmode) { File.lstat(path).mode & 0777 }
+ let(:fmode) { Puppet::FileSystem::File.new(path).lstat.mode & 0777 }
before :each do
File.open(target, "wb") {|f| f.print("some content\n")}
set_mode(0644, target)
- FileUtils.symlink(target, path)
+ Puppet::FileSystem::File.new(target).symlink(path)
end
it "should read links instead of returning their checksums" do
metadata.destination.should == target
end
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ validate_json_for_file_metadata(metadata)
+ end
end
end
@@ -209,6 +247,10 @@ describe Puppet::FileServing::Metadata do
proc { metadata.collect}.should raise_error(Errno::ENOENT)
end
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ validate_json_for_file_metadata(metadata)
+ end
end
end
@@ -222,6 +264,7 @@ describe Puppet::FileServing::Metadata do
end
it_should_behave_like "metadata collector"
+ it_should_behave_like "metadata collector symlinks"
def set_mode(mode, path)
File.chmod(mode, path)
@@ -239,6 +282,7 @@ describe Puppet::FileServing::Metadata do
end
it_should_behave_like "metadata collector"
+ it_should_behave_like "metadata collector symlinks" if Puppet.features.manages_symlinks?
describe "if ACL metadata cannot be collected" do
let(:path) { tmpdir('file_serving_metadata_acl') }
@@ -274,16 +318,24 @@ describe Puppet::FileServing::Metadata do
end
-describe Puppet::FileServing::Metadata, " when pointing to a link", :unless => Puppet.features.microsoft_windows? do
+describe Puppet::FileServing::Metadata, " when pointing to a link", :if => Puppet.features.manages_symlinks? do
describe "when links are managed" do
before do
- @file = Puppet::FileServing::Metadata.new("/base/path/my/file", :links => :manage)
- File.expects(:lstat).with("/base/path/my/file").returns stub("stat", :uid => 1, :gid => 2, :ftype => "link", :mode => 0755)
- File.expects(:readlink).with("/base/path/my/file").returns "/some/other/path"
-
+ path = "/base/path/my/file"
+ @file = Puppet::FileServing::Metadata.new(path, :links => :manage)
+ stat = stub("stat", :uid => 1, :gid => 2, :ftype => "link", :mode => 0755)
+ stub_file = stub(:readlink => "/some/other/path", :lstat => stat)
+ Puppet::FileSystem::File.expects(:new).with(path).at_least_once.returns stub_file
@checksum = Digest::MD5.hexdigest("some content\n") # Remove these when :managed links are no longer checksumed.
@file.stubs(:md5_file).returns(@checksum) #
+
+ if Puppet.features.microsoft_windows?
+ win_stat = stub('win_stat', :owner => 'snarf', :group => 'thundercats',
+ :ftype => 'link', :mode => 0755)
+ Puppet::FileServing::Metadata::WindowsStat.stubs(:new).returns win_stat
+ end
end
+
it "should store the destination of the link in :destination if links are :manage" do
@file.collect
@file.destination.should == "/some/other/path"
@@ -301,9 +353,19 @@ describe Puppet::FileServing::Metadata, " when pointing to a link", :unless => P
describe "when links are followed" do
before do
- @file = Puppet::FileServing::Metadata.new("/base/path/my/file", :links => :follow)
- File.expects(:stat).with("/base/path/my/file").returns stub("stat", :uid => 1, :gid => 2, :ftype => "file", :mode => 0755)
- File.expects(:readlink).with("/base/path/my/file").never
+ path = "/base/path/my/file"
+ @file = Puppet::FileServing::Metadata.new(path, :links => :follow)
+ stat = stub("stat", :uid => 1, :gid => 2, :ftype => "file", :mode => 0755)
+ mocked_file = mock(path, :stat => stat)
+ Puppet::FileSystem::File.expects(:new).with(path).at_least_once.returns mocked_file
+ mocked_file.expects(:readlink).never
+
+ if Puppet.features.microsoft_windows?
+ win_stat = stub('win_stat', :owner => 'snarf', :group => 'thundercats',
+ :ftype => 'file', :mode => 0755)
+ Puppet::FileServing::Metadata::WindowsStat.stubs(:new).returns win_stat
+ end
+
@checksum = Digest::MD5.hexdigest("some content\n")
@file.stubs(:md5_file).returns(@checksum)
end
diff --git a/spec/unit/file_serving/mount/file_spec.rb b/spec/unit/file_serving/mount/file_spec.rb
index 59394be46..5821f3f98 100755
--- a/spec/unit/file_serving/mount/file_spec.rb
+++ b/spec/unit/file_serving/mount/file_spec.rb
@@ -85,7 +85,7 @@ describe Puppet::FileServing::Mount::File do
include FileServingMountTesting
before do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:directory?).returns(true)
FileTest.stubs(:readable?).returns(true)
@mount = Puppet::FileServing::Mount::File.new("test")
@@ -95,12 +95,12 @@ describe Puppet::FileServing::Mount::File do
end
it "should return nil if the file is absent" do
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
@mount.complete_path("/my/path", nil).should be_nil
end
it "should write a log message if the file is absent" do
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
Puppet.expects(:info).with("File does not exist or is not accessible: /mount/my/path")
@@ -108,12 +108,12 @@ describe Puppet::FileServing::Mount::File do
end
it "should return the file path if the file is present" do
- FileTest.stubs(:exist?).with("/my/path").returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with("/my/path").returns(true)
@mount.complete_path("/my/path", nil).should == "/mount/my/path"
end
it "should treat a nil file name as the path to the mount itself" do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
@mount.complete_path(nil, nil).should == "/mount"
end
@@ -141,7 +141,7 @@ describe Puppet::FileServing::Mount::File do
include FileServingMountTesting
before do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:directory?).returns(true)
FileTest.stubs(:readable?).returns(true)
@mount = Puppet::FileServing::Mount::File.new("test")
@@ -153,7 +153,7 @@ describe Puppet::FileServing::Mount::File do
end
it "should return the results of the complete file path" do
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
@mount.expects(:complete_path).with("/my/path", "foo").returns "eh"
@mount.find("/my/path", @request).should == "eh"
end
@@ -163,7 +163,7 @@ describe Puppet::FileServing::Mount::File do
include FileServingMountTesting
before do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:directory?).returns(true)
FileTest.stubs(:readable?).returns(true)
@mount = Puppet::FileServing::Mount::File.new("test")
@@ -175,13 +175,13 @@ describe Puppet::FileServing::Mount::File do
end
it "should return the results of the complete file path as an array" do
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
@mount.expects(:complete_path).with("/my/path", "foo").returns "eh"
@mount.search("/my/path", @request).should == ["eh"]
end
it "should return nil if the complete path is nil" do
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
@mount.expects(:complete_path).with("/my/path", "foo").returns nil
@mount.search("/my/path", @request).should be_nil
end
diff --git a/spec/unit/file_serving/mount/pluginfacts_spec.rb b/spec/unit/file_serving/mount/pluginfacts_spec.rb
new file mode 100755
index 000000000..a54e45e4c
--- /dev/null
+++ b/spec/unit/file_serving/mount/pluginfacts_spec.rb
@@ -0,0 +1,73 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+require 'puppet/file_serving/mount/pluginfacts'
+
+describe Puppet::FileServing::Mount::PluginFacts do
+ before do
+ @mount = Puppet::FileServing::Mount::PluginFacts.new("pluginfacts")
+
+ @environment = stub 'environment', :module => nil
+ @options = { :recurse => true }
+ @request = stub 'request', :environment => @environment, :options => @options
+ end
+
+ describe "when finding files" do
+ it "should use the provided environment to find the modules" do
+ @environment.expects(:modules).returns []
+
+ @mount.find("foo", @request)
+ end
+
+ it "should return nil if no module can be found with a matching plugin" do
+ mod = mock 'module'
+ mod.stubs(:pluginfact).with("foo/bar").returns nil
+
+ @environment.stubs(:modules).returns [mod]
+ @mount.find("foo/bar", @request).should be_nil
+ end
+
+ it "should return the file path from the module" do
+ mod = mock 'module'
+ mod.stubs(:pluginfact).with("foo/bar").returns "eh"
+
+ @environment.stubs(:modules).returns [mod]
+ @mount.find("foo/bar", @request).should == "eh"
+ end
+ end
+
+ describe "when searching for files" do
+ it "should use the node's environment to find the modules" do
+ @environment.expects(:modules).at_least_once.returns []
+ @environment.stubs(:modulepath).returns ["/tmp/modules"]
+
+ @mount.search("foo", @request)
+ end
+
+ it "should return modulepath if no modules can be found that have plugins" do
+ mod = mock 'module'
+ mod.stubs(:pluginfacts?).returns false
+
+ @environment.stubs(:modules).returns []
+ @environment.stubs(:modulepath).returns ["/"]
+ @options.expects(:[]=).with(:recurse, false)
+ @mount.search("foo/bar", @request).should == ["/"]
+ end
+
+ it "should return nil if no modules can be found that have plugins and modulepath is invalid" do
+ mod = mock 'module'
+ mod.stubs(:pluginfacts?).returns false
+
+ @environment.stubs(:modules).returns []
+ @environment.stubs(:modulepath).returns []
+ @mount.search("foo/bar", @request).should be_nil
+ end
+
+ it "should return the plugin paths for each module that has plugins" do
+ one = stub 'module', :pluginfacts? => true, :plugin_fact_directory => "/one"
+ two = stub 'module', :pluginfacts? => true, :plugin_fact_directory => "/two"
+
+ @environment.stubs(:modules).returns [one, two]
+ @mount.search("foo/bar", @request).should == %w{/one /two}
+ end
+ end
+end
diff --git a/spec/unit/file_system/file_spec.rb b/spec/unit/file_system/file_spec.rb
new file mode 100644
index 000000000..564d4096c
--- /dev/null
+++ b/spec/unit/file_system/file_spec.rb
@@ -0,0 +1,486 @@
+require 'spec_helper'
+require 'puppet/file_system'
+require 'puppet/util/platform'
+
+describe Puppet::FileSystem::File do
+ include PuppetSpec::Files
+
+ context "#exclusive_open" do
+ it "opens ands allows updating of an existing file" do
+ file = Puppet::FileSystem::File.new(file_containing("file_to_update", "the contents"))
+
+ file.exclusive_open(0660, 'r+') do |fh|
+ old = fh.read
+ fh.truncate(0)
+ fh.rewind
+ fh.write("updated #{old}")
+ end
+
+ expect(file.read).to eq("updated the contents")
+ end
+
+ it "opens, creates ands allows updating of a new file" do
+ file = Puppet::FileSystem::File.new(tmpfile("file_to_update"))
+
+ file.exclusive_open(0660, 'w') do |fh|
+ fh.write("updated new file")
+ end
+
+ expect(file.read).to eq("updated new file")
+ end
+
+ it "excludes other processes from updating at the same time", :unless => Puppet::Util::Platform.windows? do
+ file = Puppet::FileSystem::File.new(file_containing("file_to_update", "0"))
+
+ increment_counter_in_multiple_processes(file, 5, 'r+')
+
+ expect(file.read).to eq("5")
+ end
+
+ it "excludes other processes from updating at the same time even when creating the file", :unless => Puppet::Util::Platform.windows? do
+ file = Puppet::FileSystem::File.new(tmpfile("file_to_update"))
+
+ increment_counter_in_multiple_processes(file, 5, 'a+')
+
+ expect(file.read).to eq("5")
+ end
+
+ it "times out if the lock cannot be aquired in a specified amount of time", :unless => Puppet::Util::Platform.windows? do
+ file = tmpfile("file_to_update")
+
+ child = spawn_process_that_locks(file)
+
+ expect do
+ Puppet::FileSystem::File.new(file).exclusive_open(0666, 'a', 0.1) do |f|
+ end
+ end.to raise_error(Timeout::Error)
+
+ Process.kill(9, child)
+ end
+
+ def spawn_process_that_locks(file)
+ read, write = IO.pipe
+
+ child = Kernel.fork do
+ read.close
+ Puppet::FileSystem::File.new(file).exclusive_open(0666, 'a') do |fh|
+ write.write(true)
+ write.close
+ sleep 10
+ end
+ end
+
+ write.close
+ read.read
+ read.close
+
+ child
+ end
+
+ def increment_counter_in_multiple_processes(file, num_procs, options)
+ children = []
+ 5.times do |number|
+ children << Kernel.fork do
+ file.exclusive_open(0660, options) do |fh|
+ fh.rewind
+ contents = (fh.read || 0).to_i
+ fh.truncate(0)
+ fh.rewind
+ fh.write((contents + 1).to_s)
+ end
+ exit(0)
+ end
+ end
+
+ children.each { |pid| Process.wait(pid) }
+ end
+ end
+
+ describe "symlink",
+ :if => ! Puppet.features.manages_symlinks? &&
+ Puppet.features.microsoft_windows? do
+
+ let (:file) { Puppet::FileSystem::File.new(tmpfile("somefile")) }
+ let (:missing_file) { Puppet::FileSystem::File.new(tmpfile("missingfile")) }
+ let (:expected_msg) { "This version of Windows does not support symlinks. Windows Vista / 2008 or higher is required." }
+
+ before :each do
+ FileUtils.touch(file.path)
+ end
+
+ it "should raise an error when trying to create a symlink" do
+ expect { file.symlink('foo') }.to raise_error(Puppet::Util::Windows::Error)
+ end
+
+ it "should return false when trying to check if a path is a symlink" do
+ file.symlink?.should be_false
+ end
+
+ it "should raise an error when trying to read a symlink" do
+ expect { file.readlink }.to raise_error(Puppet::Util::Windows::Error)
+ end
+
+ it "should return a File::Stat instance when calling stat on an existing file" do
+ file.stat.should be_instance_of(File::Stat)
+ end
+
+ it "should raise Errno::ENOENT when calling stat on a missing file" do
+ expect { missing_file.stat }.to raise_error(Errno::ENOENT)
+ end
+
+ it "should fall back to stat when trying to lstat a file" do
+ Puppet::Util::Windows::File.expects(:stat).with(file.path)
+
+ file.lstat
+ end
+ end
+
+ describe "symlink", :if => Puppet.features.manages_symlinks? do
+
+ let (:file) { Puppet::FileSystem::File.new(tmpfile("somefile")) }
+ let (:missing_file) { Puppet::FileSystem::File.new(tmpfile("missingfile")) }
+ let (:dir) { Puppet::FileSystem::File.new(tmpdir("somedir")) }
+
+ before :each do
+ FileUtils.touch(file.path)
+ end
+
+ it "should return true for exist? on a present file" do
+ file.exist?.should be_true
+ Puppet::FileSystem::File.exist?(file.path).should be_true
+ end
+
+ it "should return false for exist? on a non-existant file" do
+ missing_file.exist?.should be_false
+ Puppet::FileSystem::File.exist?(missing_file.path).should be_false
+ end
+
+ it "should return true for exist? on a present directory" do
+ dir.exist?.should be_true
+ Puppet::FileSystem::File.exist?(dir.path).should be_true
+ end
+
+ it "should return false for exist? on a dangling symlink" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ missing_file.symlink(symlink.path)
+
+ missing_file.exist?.should be_false
+ symlink.exist?.should be_false
+ end
+
+ it "should return true for exist? on valid symlinks" do
+ [file, dir].each do |target|
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_link"))
+ target.symlink(symlink.path)
+
+ target.exist?.should be_true
+ symlink.exist?.should be_true
+ end
+ end
+
+ it "should not create a symlink when the :noop option is specified" do
+ [file, dir].each do |target|
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_link"))
+ target.symlink(symlink.path, { :noop => true })
+
+ target.exist?.should be_true
+ symlink.exist?.should be_false
+ end
+ end
+
+ it "should raise Errno::EEXIST if trying to create a file / directory symlink when the symlink path already exists as a file" do
+ existing_file = Puppet::FileSystem::File.new(tmpfile("#{file.path.basename.to_s}_link"))
+ FileUtils.touch(existing_file.path)
+
+ [file, dir].each do |target|
+ expect { target.symlink(existing_file.path) }.to raise_error(Errno::EEXIST)
+
+ existing_file.exist?.should be_true
+ existing_file.symlink?.should be_false
+ end
+ end
+
+ it "should silently fail if trying to create a file / directory symlink when the symlink path already exists as a directory" do
+ existing_dir = Puppet::FileSystem::File.new(tmpdir("#{file.path.basename.to_s}_dir"))
+
+ [file, dir].each do |target|
+ target.symlink(existing_dir.path).should == 0
+
+ existing_dir.exist?.should be_true
+ File.directory?(existing_dir.path).should be_true
+ existing_dir.symlink?.should be_false
+ end
+ end
+
+ it "should silently fail to modify an existing directory symlink to reference a new file or directory" do
+ [file, dir].each do |target|
+ existing_dir = Puppet::FileSystem::File.new(tmpdir("#{target.path.basename.to_s}_dir"))
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{existing_dir.path.basename.to_s}_link"))
+ existing_dir.symlink(symlink.path)
+
+ symlink.readlink.should == existing_dir.path.to_s
+
+ # now try to point it at the new target, no error raised, but file system unchanged
+ target.symlink(symlink.path).should == 0
+ symlink.readlink.should == existing_dir.path.to_s
+ end
+ end
+
+ it "should raise Errno::EEXIST if trying to modify a file symlink to reference a new file or directory" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{file.path.basename.to_s}_link"))
+ file_2 = Puppet::FileSystem::File.new(tmpfile("#{file.path.basename.to_s}_2"))
+ FileUtils.touch(file_2.path)
+ # symlink -> file_2
+ file_2.symlink(symlink.path)
+
+ [file, dir].each do |target|
+ expect { target.symlink(symlink.path) }.to raise_error(Errno::EEXIST)
+ symlink.readlink.should == file_2.path.to_s
+ end
+ end
+
+ it "should delete the existing file when creating a file / directory symlink with :force when the symlink path exists as a file" do
+ [file, dir].each do |target|
+ existing_file = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_existing"))
+ FileUtils.touch(existing_file.path)
+ existing_file.symlink?.should be_false
+
+ target.symlink(existing_file.path, { :force => true })
+
+ existing_file.symlink?.should be_true
+ existing_file.readlink.should == target.path.to_s
+ end
+ end
+
+ it "should modify an existing file symlink when using :force to reference a new file or directory" do
+ [file, dir].each do |target|
+ existing_file = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_existing"))
+ FileUtils.touch(existing_file.path)
+ existing_symlink = Puppet::FileSystem::File.new(tmpfile("#{existing_file.path.basename.to_s}_link"))
+ existing_file.symlink(existing_symlink.path)
+
+ existing_symlink.readlink.should == existing_file.path.to_s
+
+ target.symlink(existing_symlink.path, { :force => true })
+
+ existing_symlink.readlink.should == target.path.to_s
+ end
+ end
+
+ it "should silently fail if trying to overwrite an existing directory with a new symlink when using :force to reference a file or directory" do
+ [file, dir].each do |target|
+ existing_dir = Puppet::FileSystem::File.new(tmpdir("#{target.path.basename.to_s}_existing"))
+
+ target.symlink(existing_dir.path, { :force => true }).should == 0
+
+ existing_dir.symlink?.should be_false
+ end
+ end
+
+ it "should silently fail if trying to modify an existing directory symlink when using :force to reference a new file or directory" do
+ [file, dir].each do |target|
+ existing_dir = Puppet::FileSystem::File.new(tmpdir("#{target.path.basename.to_s}_existing"))
+ existing_symlink = Puppet::FileSystem::File.new(tmpfile("#{existing_dir.path.basename.to_s}_link"))
+ existing_dir.symlink(existing_symlink.path)
+
+ existing_symlink.readlink.should == existing_dir.path.to_s
+
+ target.symlink(existing_symlink.path, { :force => true }).should == 0
+
+ existing_symlink.readlink.should == existing_dir.path.to_s
+ end
+ end
+
+ it "should accept a string, Pathname or object with to_str (Puppet::Util::WatchedFile) for exist?" do
+ [ tmpfile('bogus1'),
+ Pathname.new(tmpfile('bogus2')),
+ Puppet::Util::WatchedFile.new(tmpfile('bogus3'))
+ ].each { |f| Puppet::FileSystem::File.exist?(f).should be_false }
+ end
+
+ it "should return a File::Stat instance when calling stat on an existing file" do
+ file.stat.should be_instance_of(File::Stat)
+ end
+
+ it "should raise Errno::ENOENT when calling stat on a missing file" do
+ expect { missing_file.stat }.to raise_error(Errno::ENOENT)
+ end
+
+ it "should be able to create a symlink, and verify it with symlink?" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ symlink.symlink?.should be_true
+ end
+
+ it "should report symlink? as false on file, directory and missing files" do
+ [file, dir, missing_file].each do |f|
+ f.symlink?.should be_false
+ end
+ end
+
+ it "should return a File::Stat with ftype 'link' when calling lstat on a symlink pointing to existing file" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ stat = symlink.lstat
+ stat.should be_instance_of(File::Stat)
+ stat.ftype.should == 'link'
+ end
+
+ it "should return a File::Stat of ftype 'link' when calling lstat on a symlink pointing to missing file" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ missing_file.symlink(symlink.path)
+
+ stat = symlink.lstat
+ stat.should be_instance_of(File::Stat)
+ stat.ftype.should == 'link'
+ end
+
+ it "should return a File::Stat of ftype 'file' when calling stat on a symlink pointing to existing file" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ stat = symlink.stat
+ stat.should be_instance_of(File::Stat)
+ stat.ftype.should == 'file'
+ end
+
+ it "should return a File::Stat of ftype 'directory' when calling stat on a symlink pointing to existing directory" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ dir.symlink(symlink.path)
+
+ stat = symlink.stat
+ stat.should be_instance_of(File::Stat)
+ stat.ftype.should == 'directory'
+ end
+
+ it "should return a File::Stat of ftype 'file' when calling stat on a symlink pointing to another symlink" do
+ # point symlink -> file
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ # point symlink2 -> symlink
+ symlink2 = Puppet::FileSystem::File.new(tmpfile("somefile_link2"))
+ symlink.symlink(symlink2.path)
+
+ symlink2.stat.ftype.should == 'file'
+ end
+
+
+ it "should raise Errno::ENOENT when calling stat on a dangling symlink" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ missing_file.symlink(symlink.path)
+
+ expect { symlink.stat }.to raise_error(Errno::ENOENT)
+ end
+
+ it "should be able to readlink to resolve the physical path to a symlink" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ file.exist?.should be_true
+ symlink.readlink.should == file.path.to_s
+ end
+
+ it "should not resolve entire symlink chain with readlink on a symlink'd symlink" do
+ # point symlink -> file
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ file.symlink(symlink.path)
+
+ # point symlink2 -> symlink
+ symlink2 = Puppet::FileSystem::File.new(tmpfile("somefile_link2"))
+ symlink.symlink(symlink2.path)
+
+ file.exist?.should be_true
+ symlink2.readlink.should == symlink.path.to_s
+ end
+
+ it "should be able to readlink to resolve the physical path to a dangling symlink" do
+ symlink = Puppet::FileSystem::File.new(tmpfile("somefile_link"))
+ missing_file.symlink(symlink.path)
+
+ missing_file.exist?.should be_false
+ symlink.readlink.should == missing_file.path.to_s
+ end
+
+ it "should delete only the symlink and not the target when calling unlink instance method" do
+ [file, dir].each do |target|
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_link"))
+ target.symlink(symlink.path)
+
+ target.exist?.should be_true
+ symlink.readlink.should == target.path.to_s
+
+ symlink.unlink.should == 1 # count of files
+
+ target.exist?.should be_true
+ symlink.exist?.should be_false
+ end
+ end
+
+ it "should delete only the symlink and not the target when calling unlink class method" do
+ [file, dir].each do |target|
+ symlink = Puppet::FileSystem::File.new(tmpfile("#{target.path.basename.to_s}_link"))
+ target.symlink(symlink.path)
+
+ target.exist?.should be_true
+ symlink.readlink.should == target.path.to_s
+
+ Puppet::FileSystem::File.unlink(symlink.path).should == 1 # count of files
+
+ target.exist?.should be_true
+ symlink.exist?.should be_false
+ end
+ end
+
+ describe "unlink" do
+ it "should delete files with unlink" do
+ file.exist?.should be_true
+
+ file.unlink.should == 1 # count of files
+
+ file.exist?.should be_false
+ end
+
+ it "should delete files with unlink class method" do
+ file.exist?.should be_true
+
+ Puppet::FileSystem::File.unlink(file.path).should == 1 # count of files
+
+ file.exist?.should be_false
+ end
+
+ it "should delete multiple files with unlink class method" do
+ paths = (1..3).collect do |i|
+ f = Puppet::FileSystem::File.new(tmpfile("somefile_#{i}"))
+ FileUtils.touch(f.path)
+ f.exist?.should be_true
+ f.path.to_s
+ end
+
+ Puppet::FileSystem::File.unlink(*paths).should == 3 # count of files
+
+ paths.each { |p| Puppet::FileSystem::File.exist?(p).should be_false }
+ end
+
+ it "should raise Errno::EPERM or Errno::EISDIR when trying to delete a directory with the unlink class method" do
+ dir.exist?.should be_true
+
+ ex = nil
+ begin
+ Puppet::FileSystem::File.unlink(dir.path)
+ rescue Exception => e
+ ex = e
+ end
+
+ [
+ Errno::EPERM, # Windows and OSX
+ Errno::EISDIR # Linux
+ ].should include ex.class
+
+ dir.exist?.should be_true
+ end
+ end
+ end
+end
diff --git a/spec/unit/file_system/tempfile_spec.rb b/spec/unit/file_system/tempfile_spec.rb
new file mode 100644
index 000000000..5ad0a8abc
--- /dev/null
+++ b/spec/unit/file_system/tempfile_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe Puppet::FileSystem::Tempfile do
+ it "makes the name of the file available" do
+ Puppet::FileSystem::Tempfile.open('foo') do |file|
+ expect(file.path).to match(/foo/)
+ end
+ end
+
+ it "provides a writeable file" do
+ Puppet::FileSystem::Tempfile.open('foo') do |file|
+ file.write("stuff")
+ file.flush
+
+ expect(Puppet::FileSystem::File.new(file.path).read).to eq("stuff")
+ end
+ end
+
+ it "returns the value of the block" do
+ the_value = Puppet::FileSystem::Tempfile.open('foo') do |file|
+ "my value"
+ end
+
+ expect(the_value).to eq("my value")
+ end
+
+ it "unlinks the temporary file" do
+ filename = Puppet::FileSystem::Tempfile.open('foo') do |file|
+ file.path
+ end
+
+ expect(Puppet::FileSystem::File.new(filename).exist?).to be_false
+ end
+
+ it "unlinks the temporary file even if the block raises an error" do
+ filename = nil
+
+ begin
+ Puppet::FileSystem::Tempfile.open('foo') do |file|
+ filename = file.path
+ raise "error!"
+ end
+ rescue
+ end
+
+ expect(Puppet::FileSystem::File.new(filename).exist?).to be_false
+ end
+end
diff --git a/spec/unit/graph/relationship_graph_spec.rb b/spec/unit/graph/relationship_graph_spec.rb
index 7a698d769..8bd35de4d 100755
--- a/spec/unit/graph/relationship_graph_spec.rb
+++ b/spec/unit/graph/relationship_graph_spec.rb
@@ -165,12 +165,6 @@ describe Puppet::Graph::RelationshipGraph do
expect(order_resources_traversed_in(relationships)).to(
include_in_order("Notify[a]", "Notify[b]", "Notify[c]", "Notify[d]"))
end
-
- def order_resources_traversed_in(relationships)
- order_seen = []
- relationships.traverse { |resource| order_seen << resource.ref }
- order_seen
- end
end
describe "when interrupting traversal" do
diff --git a/spec/unit/hiera_puppet_spec.rb b/spec/unit/hiera_puppet_spec.rb
index 6c0f882a0..894b6e334 100644
--- a/spec/unit/hiera_puppet_spec.rb
+++ b/spec/unit/hiera_puppet_spec.rb
@@ -52,7 +52,7 @@ describe 'HieraPuppet' do
pending("This example does not apply to Puppet #{Puppet.version} because it does not have this setting")
end
- File.stubs(:exist?).with(Puppet[:hiera_config]).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(Puppet[:hiera_config]).returns(true)
HieraPuppet.send(:hiera_config_file).should == Puppet[:hiera_config]
end
@@ -64,7 +64,7 @@ describe 'HieraPuppet' do
end
Puppet.settings[:confdir] = "/dev/null/puppet"
hiera_config = File.join(Puppet[:confdir], 'hiera.yaml')
- File.stubs(:exist?).with(hiera_config).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(hiera_config).returns(true)
HieraPuppet.send(:hiera_config_file).should == hiera_config
end
diff --git a/spec/unit/indirector/catalog/compiler_spec.rb b/spec/unit/indirector/catalog/compiler_spec.rb
index ff32f7c7b..c968794e4 100755
--- a/spec/unit/indirector/catalog/compiler_spec.rb
+++ b/spec/unit/indirector/catalog/compiler_spec.rb
@@ -24,12 +24,12 @@ describe Puppet::Resource::Catalog::Compiler do
end
it "should cache the server metadata and reuse it" do
+ Puppet[:node_terminus] = :memory
+ Puppet::Node.indirection.save(Puppet::Node.new("node1"))
+ Puppet::Node.indirection.save(Puppet::Node.new("node2"))
+
compiler = Puppet::Resource::Catalog::Compiler.new
- node1 = stub 'node1', :merge => nil
- node2 = stub 'node2', :merge => nil
compiler.stubs(:compile)
- Puppet::Node.indirection.stubs(:find).with('node1', has_entry(:environment => anything)).returns(node1)
- Puppet::Node.indirection.stubs(:find).with('node2', has_entry(:environment => anything)).returns(node2)
compiler.find(Puppet::Indirector::Request.new(:catalog, :find, 'node1', nil, :node => 'node1'))
compiler.find(Puppet::Indirector::Request.new(:catalog, :find, 'node2', nil, :node => 'node2'))
@@ -175,19 +175,16 @@ describe Puppet::Resource::Catalog::Compiler do
end
describe "when finding nodes" do
- before do
+ it "should look node information up via the Node class with the provided key" do
Facter.stubs(:value).returns("whatever")
- @compiler = Puppet::Resource::Catalog::Compiler.new
- @name = "me"
- @node = mock 'node'
- @request = Puppet::Indirector::Request.new(:catalog, :find, @name, nil)
- @compiler.stubs(:compile)
- end
+ node = Puppet::Node.new('node')
+ compiler = Puppet::Resource::Catalog::Compiler.new
+ request = Puppet::Indirector::Request.new(:catalog, :find, "me", nil)
+ compiler.stubs(:compile)
- it "should look node information up via the Node class with the provided key" do
- @node.stubs :merge
- Puppet::Node.indirection.expects(:find).with(@name, anything).returns(@node)
- @compiler.find(@request)
+ Puppet::Node.indirection.expects(:find).with("me", anything).returns(node)
+
+ compiler.find(request)
end
end
@@ -197,11 +194,10 @@ describe Puppet::Resource::Catalog::Compiler do
Facter.expects(:value).with('fqdn').returns("my.server.com")
Facter.expects(:value).with('ipaddress').returns("my.ip.address")
@compiler = Puppet::Resource::Catalog::Compiler.new
- @name = "me"
- @node = mock 'node'
- @request = Puppet::Indirector::Request.new(:catalog, :find, @name, nil)
+ @node = Puppet::Node.new("me")
+ @request = Puppet::Indirector::Request.new(:catalog, :find, "me", nil)
@compiler.stubs(:compile)
- Puppet::Node.indirection.stubs(:find).with(@name, anything).returns(@node)
+ Puppet::Node.indirection.stubs(:find).with("me", anything).returns(@node)
end
it "should add the server's Puppet version to the node's parameters as 'serverversion'" do
diff --git a/spec/unit/indirector/certificate_status/file_spec.rb b/spec/unit/indirector/certificate_status/file_spec.rb
index c880bf786..83d4de210 100755
--- a/spec/unit/indirector/certificate_status/file_spec.rb
+++ b/spec/unit/indirector/certificate_status/file_spec.rb
@@ -87,16 +87,14 @@ describe "Puppet::Indirector::CertificateStatus::File" do
retrieved_host.certificate_request.content.to_s.chomp.should == @host.certificate_request.content.to_s.chomp
end
- it "should return the Puppet::SSL::Host when a public key exist for the host" do
- pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
- generate_signed_cert(@host)
- request = Puppet::Indirector::Request.new(:certificate_status, :find, "foo", @host)
+ it "should return the Puppet::SSL::Host when a public key exists for the host" do
+ generate_signed_cert(@host)
+ request = Puppet::Indirector::Request.new(:certificate_status, :find, "foo", @host)
- retrieved_host = @terminus.find(request)
+ retrieved_host = @terminus.find(request)
- retrieved_host.name.should == @host.name
- retrieved_host.certificate.content.to_s.chomp.should == @host.certificate.content.to_s.chomp
- end
+ retrieved_host.name.should == @host.name
+ retrieved_host.certificate.content.to_s.chomp.should == @host.certificate.content.to_s.chomp
end
it "should return nil when neither a CSR nor public key exist for the host" do
@@ -122,12 +120,10 @@ describe "Puppet::Indirector::CertificateStatus::File" do
end
it "should sign the on-disk CSR when it is present" do
- pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
- signed_host = generate_signed_cert(@host)
+ signed_host = generate_signed_cert(@host)
- signed_host.state.should == "signed"
- Puppet::SSL::Certificate.indirection.find("foobar").should be_instance_of(Puppet::SSL::Certificate)
- end
+ signed_host.state.should == "signed"
+ Puppet::SSL::Certificate.indirection.find("foobar").should be_instance_of(Puppet::SSL::Certificate)
end
end
@@ -142,11 +138,9 @@ describe "Puppet::Indirector::CertificateStatus::File" do
end
it "should revoke the certificate when it is present" do
- pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
- generate_revoked_cert(@host)
+ generate_revoked_cert(@host)
- @host.state.should == 'revoked'
- end
+ @host.state.should == 'revoked'
end
end
end
@@ -163,39 +157,35 @@ describe "Puppet::Indirector::CertificateStatus::File" do
end
it "should clean certs, cert requests, keys" do
- pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
- signed_host = Puppet::SSL::Host.new("clean_signed_cert")
- generate_signed_cert(signed_host)
- signed_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_signed_cert", signed_host)
- @terminus.destroy(signed_request).should == "Deleted for clean_signed_cert: Puppet::SSL::Certificate, Puppet::SSL::Key"
-
- requested_host = Puppet::SSL::Host.new("clean_csr")
- generate_csr(requested_host)
- csr_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_csr", requested_host)
- @terminus.destroy(csr_request).should == "Deleted for clean_csr: Puppet::SSL::CertificateRequest, Puppet::SSL::Key"
- end
+ signed_host = Puppet::SSL::Host.new("clean_signed_cert")
+ generate_signed_cert(signed_host)
+ signed_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_signed_cert", signed_host)
+ @terminus.destroy(signed_request).should == "Deleted for clean_signed_cert: Puppet::SSL::Certificate, Puppet::SSL::Key"
+
+ requested_host = Puppet::SSL::Host.new("clean_csr")
+ generate_csr(requested_host)
+ csr_request = Puppet::Indirector::Request.new(:certificate_status, :delete, "clean_csr", requested_host)
+ @terminus.destroy(csr_request).should == "Deleted for clean_csr: Puppet::SSL::CertificateRequest, Puppet::SSL::Key"
end
end
describe "when searching" do
it "should return a list of all hosts with certificate requests, signed certs, or revoked certs" do
- pending("porting to Windows", :if => Puppet.features.microsoft_windows?) do
- Puppet.settings.use(:main)
+ Puppet.settings.use(:main)
- signed_host = Puppet::SSL::Host.new("signed_host")
- generate_signed_cert(signed_host)
+ signed_host = Puppet::SSL::Host.new("signed_host")
+ generate_signed_cert(signed_host)
- requested_host = Puppet::SSL::Host.new("requested_host")
- generate_csr(requested_host)
+ requested_host = Puppet::SSL::Host.new("requested_host")
+ generate_csr(requested_host)
- revoked_host = Puppet::SSL::Host.new("revoked_host")
- generate_revoked_cert(revoked_host)
+ revoked_host = Puppet::SSL::Host.new("revoked_host")
+ generate_revoked_cert(revoked_host)
- retrieved_hosts = @terminus.search(Puppet::Indirector::Request.new(:certificate_status, :search, "all", signed_host))
+ retrieved_hosts = @terminus.search(Puppet::Indirector::Request.new(:certificate_status, :search, "all", signed_host))
- results = retrieved_hosts.map {|h| [h.name, h.state]}.sort{ |h,i| h[0] <=> i[0] }
- results.should == [["ca","signed"],["requested_host","requested"],["revoked_host","revoked"],["signed_host","signed"]]
- end
+ results = retrieved_hosts.map {|h| [h.name, h.state]}.sort{ |h,i| h[0] <=> i[0] }
+ results.should == [["ca","signed"],["requested_host","requested"],["revoked_host","revoked"],["signed_host","signed"]]
end
end
end
diff --git a/spec/unit/indirector/data_binding/hiera_spec.rb b/spec/unit/indirector/data_binding/hiera_spec.rb
index 98883bb9d..7ab3b27fc 100644
--- a/spec/unit/indirector/data_binding/hiera_spec.rb
+++ b/spec/unit/indirector/data_binding/hiera_spec.rb
@@ -2,8 +2,32 @@ require 'spec_helper'
require 'puppet/indirector/data_binding/hiera'
describe Puppet::DataBinding::Hiera do
- it "should be a subclass of the Hiera terminus" do
- Puppet::DataBinding::Hiera.superclass.should equal(Puppet::Indirector::Hiera)
+ include PuppetSpec::Files
+
+ def write_hiera_config(config_file, datadir)
+ File.open(config_file, 'w') do |f|
+ f.write("---
+ :yaml:
+ :datadir: #{datadir}
+ :hierarchy: ['global', 'invalid']
+ :logger: 'noop'
+ :backends: ['yaml']
+ ")
+ end
+ end
+
+ def request(key)
+ Puppet::Indirector::Request.new(:hiera, :find, key, nil)
+ end
+
+ before do
+ hiera_config_file = tmpfile("hiera.yaml")
+ Puppet.settings[:hiera_config] = hiera_config_file
+ write_hiera_config(hiera_config_file, my_fixture_dir)
+ end
+
+ after do
+ Puppet::DataBinding::Hiera.instance_variable_set(:@hiera, nil)
end
it "should have documentation" do
@@ -18,4 +42,73 @@ describe Puppet::DataBinding::Hiera do
it "should have its name set to :hiera" do
Puppet::DataBinding::Hiera.name.should == :hiera
end
+ it "should be the default data_binding terminus" do
+ Puppet.settings[:data_binding_terminus].should == :hiera
+ end
+
+ it "should raise an error if we don't have the hiera feature" do
+ Puppet.features.expects(:hiera?).returns(false)
+ lambda { Puppet::DataBinding::Hiera.new }.should raise_error RuntimeError,
+ "Hiera terminus not supported without hiera library"
+ end
+
+ describe "the behavior of the hiera_config method", :if => Puppet.features.hiera? do
+ it "should override the logger and set it to puppet" do
+ Puppet::DataBinding::Hiera.hiera_config[:logger].should == "puppet"
+ end
+
+ context "when the Hiera configuration file does not exist" do
+ let(:path) { File.expand_path('/doesnotexist') }
+
+ before do
+ Puppet.settings[:hiera_config] = path
+ end
+
+ it "should log a warning" do
+ Puppet.expects(:warning).with(
+ "Config file #{path} not found, using Hiera defaults")
+ Puppet::DataBinding::Hiera.hiera_config
+ end
+
+ it "should only configure the logger and set it to puppet" do
+ Puppet.expects(:warning).with(
+ "Config file #{path} not found, using Hiera defaults")
+ Puppet::DataBinding::Hiera.hiera_config.should == { :logger => 'puppet' }
+ end
+ end
+ end
+
+ describe "the behavior of the find method", :if => Puppet.features.hiera? do
+
+ let(:data_binder) { Puppet::DataBinding::Hiera.new }
+
+ it "should support looking up an integer" do
+ data_binder.find(request("integer")).should == 3000
+ end
+
+ it "should support looking up a string" do
+ data_binder.find(request("string")).should == 'apache'
+ end
+
+ it "should support looking up an array" do
+ data_binder.find(request("array")).should == [
+ '0.ntp.puppetlabs.com',
+ '1.ntp.puppetlabs.com',
+ ]
+ end
+
+ it "should support looking up a hash" do
+ data_binder.find(request("hash")).should == {
+ 'user' => 'Hightower',
+ 'group' => 'admin',
+ 'mode' => '0644'
+ }
+ end
+
+ it "raises a data binding error if hiera cannot parse the yaml data" do
+ expect do
+ data_binder.find(request('invalid'))
+ end.to raise_error(Puppet::DataBinding::LookupError)
+ end
+ end
end
diff --git a/spec/unit/indirector/direct_file_server_spec.rb b/spec/unit/indirector/direct_file_server_spec.rb
index 234f25ef9..8b08195bb 100755
--- a/spec/unit/indirector/direct_file_server_spec.rb
+++ b/spec/unit/indirector/direct_file_server_spec.rb
@@ -26,12 +26,12 @@ describe Puppet::Indirector::DirectFileServer do
describe Puppet::Indirector::DirectFileServer, "when finding a single file" do
it "should return nil if the file does not exist" do
- FileTest.expects(:exists?).with(@path).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns false
@server.find(@request).should be_nil
end
it "should return a Content instance created with the full path to the file if the file exists" do
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
@model.expects(:new).returns(:mycontent)
@server.find(@request).should == :mycontent
end
@@ -42,7 +42,7 @@ describe Puppet::Indirector::DirectFileServer do
before do
@data = mock 'content'
@data.stubs(:collect)
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
end
it "should pass the full path to the instance" do
@@ -61,18 +61,18 @@ describe Puppet::Indirector::DirectFileServer do
describe Puppet::Indirector::DirectFileServer, "when searching for multiple files" do
it "should return nil if the file does not exist" do
- FileTest.expects(:exists?).with(@path).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns false
@server.find(@request).should be_nil
end
it "should use :path2instances from the terminus_helper to return instances if the file exists" do
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
@server.expects(:path2instances)
@server.search(@request)
end
it "should pass the original request to :path2instances" do
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
@server.expects(:path2instances).with(@request, @path)
@server.search(@request)
end
diff --git a/spec/unit/indirector/facts/facter_spec.rb b/spec/unit/indirector/facts/facter_spec.rb
index 3e301a5a5..4c55ec6c3 100755
--- a/spec/unit/indirector/facts/facter_spec.rb
+++ b/spec/unit/indirector/facts/facter_spec.rb
@@ -48,6 +48,9 @@ describe Puppet::Node::Facts::Facter do
Facter.stubs(:to_hash).returns({})
@name = "me"
@request = stub 'request', :key => @name
+ @environment = stub 'environment'
+ @request.stubs(:environment).returns(@environment)
+ @request.environment.stubs(:modules).returns([])
end
describe Puppet::Node::Facts::Facter, " when finding facts" do
@@ -58,6 +61,15 @@ describe Puppet::Node::Facts::Facter do
@facter.find(@request)
end
+ it "should include external facts when feature is present" do
+ clear = sequence 'clear'
+ Puppet.features.stubs(:external_facts?).returns(:true)
+ Puppet::Node::Facts::Facter.expects(:setup_external_facts).in_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
@@ -131,6 +143,20 @@ describe Puppet::Node::Facts::Facter do
Puppet::Node::Facts::Facter.load_facts_in_dir("mydir")
end
+ it "should include pluginfactdest when loading external facts",
+ :if => Puppet.features.external_facts?, :unless => Puppet.features.microsoft_windows? do
+ Puppet[:pluginfactdest] = "/plugin/dest"
+ @facter.find(@request)
+ Facter::Util::Config.external_facts_dirs.include?("/plugin/dest")
+ end
+
+ it "should include pluginfactdest when loading external facts",
+ :if => Puppet.features.external_facts?, :if => Puppet.features.microsoft_windows? do
+ Puppet[:pluginfactdest] = "/plugin/dest"
+ @facter.find(@request)
+ Facter::Util::Config.external_facts_dirs.include?("C:/plugin/dest")
+ end
+
describe "when loading fact plugins from disk" do
let(:one) { File.expand_path("one") }
let(:two) { File.expand_path("two") }
@@ -160,5 +186,12 @@ describe Puppet::Node::Facts::Facter do
Puppet::Node::Facts::Facter.load_fact_plugins
end
+
+ it "should include module plugin facts when present", :if => Puppet.features.external_facts? do
+ mod = Puppet::Module.new("mymodule", "#{one}/mymodule", @request.environment)
+ @request.environment.stubs(:modules).returns([mod])
+ @facter.find(@request)
+ Facter::Util::Config.external_facts_dirs.include?("#{one}/mymodule/facts.d")
+ end
end
end
diff --git a/spec/unit/indirector/file_bucket_file/file_spec.rb b/spec/unit/indirector/file_bucket_file/file_spec.rb
index 37529e5d5..2f9e140f7 100755
--- a/spec/unit/indirector/file_bucket_file/file_spec.rb
+++ b/spec/unit/indirector/file_bucket_file/file_spec.rb
@@ -2,18 +2,11 @@
require 'spec_helper'
require 'puppet/indirector/file_bucket_file/file'
+require 'puppet/util/platform'
describe Puppet::FileBucketFile::File do
include PuppetSpec::Files
- it "should be a subclass of the Code terminus class" do
- Puppet::FileBucketFile::File.superclass.should equal(Puppet::Indirector::Code)
- end
-
- it "should have documentation" do
- Puppet::FileBucketFile::File.doc.should be_instance_of(String)
- end
-
describe "non-stubbing tests" do
include PuppetSpec::Files
@@ -23,7 +16,7 @@ describe Puppet::FileBucketFile::File do
def save_bucket_file(contents, path = "/who_cares")
bucket_file = Puppet::FileBucket::File.new(contents)
- Puppet::FileBucket::File.indirection.save(bucket_file, "md5/#{Digest::MD5.hexdigest(contents)}#{path}")
+ Puppet::FileBucket::File.indirection.save(bucket_file, "#{bucket_file.name}#{path}")
bucket_file.checksum_data
end
@@ -34,17 +27,58 @@ describe Puppet::FileBucketFile::File do
result.contents.should be_empty
end
+ it "deals with multiple processes saving at the same time", :unless => Puppet::Util::Platform.windows? do
+ bucket_file = Puppet::FileBucket::File.new("contents")
+
+ children = []
+ 5.times do |count|
+ children << Kernel.fork do
+ save_bucket_file("contents", "/testing")
+ exit(0)
+ end
+ end
+ children.each { |child| Process.wait(child) }
+
+ paths = File.read("#{Puppet[:bucketdir]}/9/8/b/f/7/d/8/c/98bf7d8c15784f0a3d63204441e1e2aa/paths").lines.to_a
+ paths.length.should == 1
+ Puppet::FileBucket::File.indirection.head("#{bucket_file.checksum_type}/#{bucket_file.checksum_data}/testing").should be_true
+ end
+
+ it "fails if the contents collide with existing contents" do
+ # This is the shortest known MD5 collision. See http://eprint.iacr.org/2010/643.pdf
+ first_contents = [0x6165300e,0x87a79a55,0xf7c60bd0,0x34febd0b,
+ 0x6503cf04,0x854f709e,0xfb0fc034,0x874c9c65,
+ 0x2f94cc40,0x15a12deb,0x5c15f4a3,0x490786bb,
+ 0x6d658673,0xa4341f7d,0x8fd75920,0xefd18d5a].pack("I" * 16)
+
+ collision_contents = [0x6165300e,0x87a79a55,0xf7c60bd0,0x34febd0b,
+ 0x6503cf04,0x854f749e,0xfb0fc034,0x874c9c65,
+ 0x2f94cc40,0x15a12deb,0xdc15f4a3,0x490786bb,
+ 0x6d658673,0xa4341f7d,0x8fd75920,0xefd18d5a].pack("I" * 16)
+
+ save_bucket_file(first_contents, "/foo/bar")
+
+ expect do
+ save_bucket_file(collision_contents, "/foo/bar")
+ end.to raise_error(Puppet::FileBucket::BucketError, /Got passed new contents/)
+ end
+
describe "when supplying a path" do
it "should store the path if not already stored" do
checksum = save_bucket_file("stuff\r\n", "/foo/bar")
+
dir_path = "#{Puppet[:bucketdir]}/f/c/7/7/7/c/0/b/fc777c0bc467e1ab98b4c6915af802ec"
- IO.binread("#{dir_path}/contents").should == "stuff\r\n"
- File.read("#{dir_path}/paths").should == "foo/bar\n"
+ contents_file = Puppet::FileSystem::File.new("#{dir_path}/contents")
+ paths_file = Puppet::FileSystem::File.new("#{dir_path}/paths")
+ contents_file.binread.should == "stuff\r\n"
+ paths_file.read.should == "foo/bar\n"
end
it "should leave the paths file alone if the path is already stored" do
checksum = save_bucket_file("stuff", "/foo/bar")
+
checksum = save_bucket_file("stuff", "/foo/bar")
+
dir_path = "#{Puppet[:bucketdir]}/c/1/3/d/8/8/c/b/c13d88cb4cb02003daedb8a84e5d272a"
File.read("#{dir_path}/contents").should == "stuff"
File.read("#{dir_path}/paths").should == "foo/bar\n"
@@ -52,7 +86,9 @@ describe Puppet::FileBucketFile::File do
it "should store an additional path if the new path differs from those already stored" do
checksum = save_bucket_file("stuff", "/foo/bar")
+
checksum = save_bucket_file("stuff", "/foo/baz")
+
dir_path = "#{Puppet[:bucketdir]}/c/1/3/d/8/8/c/b/c13d88cb4cb02003daedb8a84e5d272a"
File.read("#{dir_path}/contents").should == "stuff"
File.read("#{dir_path}/paths").should == "foo/bar\nfoo/baz\n"
@@ -62,6 +98,7 @@ describe Puppet::FileBucketFile::File do
describe "when not supplying a path" do
it "should save the file and create an empty paths file" do
checksum = save_bucket_file("stuff", "")
+
dir_path = "#{Puppet[:bucketdir]}/c/1/3/d/8/8/c/b/c13d88cb4cb02003daedb8a84e5d272a"
File.read("#{dir_path}/contents").should == "stuff"
File.read("#{dir_path}/paths").should == ""
@@ -78,16 +115,18 @@ describe Puppet::FileBucketFile::File do
it "should return false/nil if the file is bucketed but with a different path" do
checksum = save_bucket_file("I'm the contents of a file", '/foo/bar')
+
Puppet::FileBucket::File.indirection.head("md5/#{checksum}/foo/baz").should == false
Puppet::FileBucket::File.indirection.find("md5/#{checksum}/foo/baz").should == nil
end
it "should return true/file if the file is already bucketed with the given path" do
contents = "I'm the contents of a file"
+
checksum = save_bucket_file(contents, '/foo/bar')
+
Puppet::FileBucket::File.indirection.head("md5/#{checksum}/foo/bar").should == true
find_result = Puppet::FileBucket::File.indirection.find("md5/#{checksum}/foo/bar")
- find_result.should be_a(Puppet::FileBucket::File)
find_result.checksum.should == "{md5}#{checksum}"
find_result.to_s.should == contents
end
@@ -105,10 +144,11 @@ describe Puppet::FileBucketFile::File do
it "should return true/file if the file is already bucketed" do
contents = "I'm the contents of a file"
+
checksum = save_bucket_file(contents, '/foo/bar')
+
Puppet::FileBucket::File.indirection.head("md5/#{checksum}#{trailing_string}").should == true
find_result = Puppet::FileBucket::File.indirection.find("md5/#{checksum}#{trailing_string}")
- find_result.should be_a(Puppet::FileBucket::File)
find_result.checksum.should == "{md5}#{checksum}"
find_result.to_s.should == contents
end
@@ -126,6 +166,7 @@ describe Puppet::FileBucketFile::File do
it "should generate a proper diff if there is a diff" do
checksum1 = save_bucket_file("foo\nbar\nbaz")
checksum2 = save_bucket_file("foo\nbiz\nbaz")
+
diff = Puppet::FileBucket::File.indirection.find("md5/#{checksum1}", :diff_with => checksum2)
diff.should == <<HERE
2c2
@@ -136,27 +177,23 @@ HERE
end
it "should raise an exception if the hash to diff against isn't found" do
- checksum = save_bucket_file("whatever")
bogus_checksum = "d1bf072d0e2c6e20e3fbd23f022089a1"
- lambda { Puppet::FileBucket::File.indirection.find("md5/#{checksum}", :diff_with => bogus_checksum) }.should raise_error "could not find diff_with #{bogus_checksum}"
+ checksum = save_bucket_file("whatever")
+
+ expect do
+ Puppet::FileBucket::File.indirection.find("md5/#{checksum}", :diff_with => bogus_checksum)
+ end.to raise_error "could not find diff_with #{bogus_checksum}"
end
it "should return nil if the hash to diff from isn't found" do
- checksum = save_bucket_file("whatever")
bogus_checksum = "d1bf072d0e2c6e20e3fbd23f022089a1"
+ checksum = save_bucket_file("whatever")
+
Puppet::FileBucket::File.indirection.find("md5/#{bogus_checksum}", :diff_with => checksum).should == nil
end
end
end
- describe "when initializing" do
- it "should use the filebucket settings section" do
- Puppet.settings.expects(:use).with(:filebucket)
- Puppet::FileBucketFile::File.new
- end
- end
-
-
[true, false].each do |override_bucket_path|
describe "when bucket path #{if override_bucket_path then 'is' else 'is not' end} overridden" do
[true, false].each do |supply_path|
@@ -245,32 +282,4 @@ HERE
end
end
end
-
- describe "when verifying identical files" do
- let(:contents) { "file\r\n contents" }
- let(:digest) { "8b3702ad1aed1ace7e32bde76ffffb2d" }
- let(:checksum) { "{md5}#{@digest}" }
- let(:bucketdir) { tmpdir('file_bucket_file') }
- let(:destdir) { "#{bucketdir}/8/b/3/7/0/2/a/d/8b3702ad1aed1ace7e32bde76ffffb2d" }
- let(:bucket) { Puppet::FileBucket::File.new(contents) }
-
- before :each do
- Puppet[:bucketdir] = bucketdir
- FileUtils.mkdir_p(destdir)
- end
-
- it "should raise an error if the files don't match" do
- File.open(File.join(destdir, 'contents'), 'wb') { |f| f.print "corrupt contents" }
-
- lambda{
- Puppet::FileBucketFile::File.new.send(:verify_identical_file!, bucket)
- }.should raise_error(Puppet::FileBucket::BucketError)
- end
-
- it "should do nothing if the files match" do
- File.open(File.join(destdir, 'contents'), 'wb') { |f| f.print contents }
-
- Puppet::FileBucketFile::File.new.send(:verify_identical_file!, bucket)
- end
- end
end
diff --git a/spec/unit/indirector/file_metadata/file_spec.rb b/spec/unit/indirector/file_metadata/file_spec.rb
index d51c65882..459c1dbe8 100755
--- a/spec/unit/indirector/file_metadata/file_spec.rb
+++ b/spec/unit/indirector/file_metadata/file_spec.rb
@@ -19,7 +19,7 @@ describe Puppet::Indirector::FileMetadata::File do
@uri = Puppet::Util.path_to_uri(@path).to_s
@data = mock 'metadata'
@data.stubs(:collect)
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
@request = Puppet::Indirector::Request.new(:file_metadata, :find, @uri, nil)
end
@@ -42,7 +42,7 @@ describe Puppet::Indirector::FileMetadata::File do
end
it "should collect the attributes of the instances returned" do
- FileTest.expects(:exists?).with(@path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns true
@metadata.expects(:path2instances).returns( [mock("one", :collect => nil), mock("two", :collect => nil)] )
@metadata.search(@request)
end
diff --git a/spec/unit/indirector/file_server_spec.rb b/spec/unit/indirector/file_server_spec.rb
index 00649875f..6f491b065 100755
--- a/spec/unit/indirector/file_server_spec.rb
+++ b/spec/unit/indirector/file_server_spec.rb
@@ -154,7 +154,7 @@ describe Puppet::Indirector::FileServer do
@mount.expects(:search).with { |key, request| key == "rel/path" }.returns %w{/one /two}
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
one = mock 'fileset_one'
Puppet::FileServing::Fileset.expects(:new).with("/one", @request).returns(one)
@@ -171,7 +171,7 @@ describe Puppet::Indirector::FileServer do
@mount.expects(:search).with { |key, request| key == "rel/path" }.returns []
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::FileServing::Fileset.expects(:merge).returns("one" => "/one", "two" => "/two")
@@ -193,7 +193,7 @@ describe Puppet::Indirector::FileServer do
@mount.expects(:search).with { |key, request| key == "rel/path" }.returns []
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::FileServing::Fileset.expects(:merge).returns("one" => "/one")
@@ -211,7 +211,7 @@ describe Puppet::Indirector::FileServer do
@mount.expects(:search).with { |key, options| key == "rel/path" }.returns []
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::FileServing::Fileset.expects(:merge).returns("one" => "/one")
diff --git a/spec/unit/indirector/hiera_spec.rb b/spec/unit/indirector/hiera_spec.rb
deleted file mode 100644
index 36b598c37..000000000
--- a/spec/unit/indirector/hiera_spec.rb
+++ /dev/null
@@ -1,154 +0,0 @@
-require 'spec_helper'
-require 'puppet/indirector/hiera'
-require 'hiera/backend'
-
-describe Puppet::Indirector::Hiera do
- include PuppetSpec::Files
-
- def write_hiera_config(config_file, datadir)
- File.open(config_file, 'w') do |f|
- f.write("---
- :yaml:
- :datadir: #{datadir}
- :hierarchy: ['global']
- :logger: 'noop'
- :backends: ['yaml']
- ")
- end
- end
-
- before do
- Puppet.settings[:hiera_config] = hiera_config_file
- write_hiera_config(hiera_config_file, datadir)
-
- Puppet::Indirector::Terminus.stubs(:register_terminus_class)
- Puppet::Indirector::Indirection.stubs(:instance).returns(indirection)
-
- module Testing; end
- @hiera_class = class Testing::Hiera < Puppet::Indirector::Hiera
- self
- end
- end
-
- let(:model) { mock('model') }
- let(:options) { {:host => 'foo' } }
-
- let(:request_integer) do
- stub('request', :key => "integer", :options => options)
- end
-
- let(:request_string) do
- stub('request', :key => "string", :options => options)
- end
-
- let(:request_array) do
- stub('request', :key => "array", :options => options)
- end
-
- let(:request_hash) do
- stub('request', :key => "hash", :options => options)
- end
-
- let(:indirection) do
- stub('indirection', :name => :none, :register_terminus_type => nil,
- :model => model)
- end
-
- let(:facts) do
- { 'fqdn' => 'agent.testing.com' }
- end
- let(:facter_obj) { stub(:values => facts) }
-
- let(:hiera_config_file) do
- tmpfile("hiera.yaml")
- end
-
- let(:datadir) { my_fixture_dir }
-
- it "should be the default data_binding terminus" do
- Puppet.settings[:data_binding_terminus].should == :hiera
- end
-
- it "should raise an error if we don't have the hiera feature" do
- Puppet.features.expects(:hiera?).returns(false)
- lambda { @hiera_class.new }.should raise_error RuntimeError,
- "Hiera terminus not supported without hiera library"
- end
-
- describe "the behavior of the hiera_config method", :if => Puppet.features.hiera? do
- let(:default_hiera_config) do
- {
- :logger => "puppet",
- :backends => ["yaml"],
- :yaml => { :datadir => datadir },
- :hierarchy => ["global"]
- }
- end
-
- it "should load the hiera config file by delegating to Hiera" do
- Hiera::Config.expects(:load).with(hiera_config_file).returns({})
- @hiera_class.hiera_config
- end
-
- it "should override the logger and set it to puppet" do
- @hiera_class.hiera_config[:logger].should == "puppet"
- end
-
- it "should return a hiera configuration hash" do
- results = @hiera_class.hiera_config
- default_hiera_config.each do |key,value|
- results[key].should == value
- end
- results.should be_a_kind_of Hash
- end
-
- context "when the Hiera configuration file does not exist" do
- let(:path) { File.expand_path('/doesnotexist') }
-
- before do
- Puppet.settings[:hiera_config] = path
- end
-
- it "should log a warning" do
- Puppet.expects(:warning).with(
- "Config file #{path} not found, using Hiera defaults")
- @hiera_class.hiera_config
- end
-
- it "should only configure the logger and set it to puppet" do
- Puppet.expects(:warning).with(
- "Config file #{path} not found, using Hiera defaults")
- @hiera_class.hiera_config.should == { :logger => 'puppet' }
- end
- end
- end
-
- describe "the behavior of the find method", :if => Puppet.features.hiera? do
-
- let(:data_binder) { @hiera_class.new }
-
- it "should support looking up an integer" do
- data_binder.find(request_integer).should == 3000
- end
-
- it "should support looking up a string" do
- data_binder.find(request_string).should == 'apache'
- end
-
- it "should support looking up an array" do
- data_binder.find(request_array).should == [
- '0.ntp.puppetlabs.com',
- '1.ntp.puppetlabs.com',
- ]
- end
-
- it "should support looking up a hash" do
- data_binder.find(request_hash).should == {
- 'user' => 'Hightower',
- 'group' => 'admin',
- 'mode' => '0644'
- }
- end
- end
-end
-
diff --git a/spec/unit/indirector/json_spec.rb b/spec/unit/indirector/json_spec.rb
index c80bcd33c..664a32749 100755
--- a/spec/unit/indirector/json_spec.rb
+++ b/spec/unit/indirector/json_spec.rb
@@ -131,20 +131,20 @@ describe Puppet::Indirector::JSON do
with_content('hello') do
subject.destroy(request)
end
- File.should_not be_exist file
+ Puppet::FileSystem::File.exist?(file).should be_false
end
it "silently succeeds when files don't exist" do
- File.unlink(file) rescue nil
+ Puppet::FileSystem::File.unlink(file) rescue nil
subject.destroy(request).should be_true
end
it "raises an informative error for other failures" do
- File.stubs(:unlink).with(file).raises(Errno::EPERM, 'fake permission problem')
+ Puppet::FileSystem::File.stubs(:unlink).with(file).raises(Errno::EPERM, 'fake permission problem')
with_content('hello') do
expect { subject.destroy(request) }.to raise_error Puppet::Error
end
- File.unstub(:unlink) # thanks, mocha
+ Puppet::FileSystem::File.unstub(:unlink) # thanks, mocha
end
end
end
diff --git a/spec/unit/indirector/key/file_spec.rb b/spec/unit/indirector/key/file_spec.rb
index 57be73691..95c212523 100755
--- a/spec/unit/indirector/key/file_spec.rb
+++ b/spec/unit/indirector/key/file_spec.rb
@@ -64,33 +64,32 @@ describe Puppet::SSL::Key::File do
end
it "should save the public key when saving the private key" do
- Puppet.settings.stubs(:writesub)
+ fh = StringIO.new
- fh = mock 'filehandle'
-
- Puppet.settings.expects(:writesub).with(:publickeydir, @public_key_path).yields fh
+ Puppet.settings.setting(:publickeydir).expects(:open_file).with(@public_key_path, 'w').yields fh
+ Puppet.settings.setting(:privatekeydir).stubs(:open_file)
@public_key.expects(:to_pem).returns "my pem"
- fh.expects(:print).with "my pem"
-
@searcher.save(@request)
+
+ expect(fh.string).to eq("my pem")
end
it "should destroy the public key when destroying the private key" do
- File.stubs(:unlink).with(@private_key_path)
- FileTest.stubs(:exist?).with(@private_key_path).returns true
- FileTest.expects(:exist?).with(@public_key_path).returns true
- File.expects(:unlink).with(@public_key_path)
+ Puppet::FileSystem::File.stubs(:unlink).with(@private_key_path)
+ Puppet::FileSystem::File.stubs(:exist?).with(@private_key_path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@public_key_path).returns true
+ Puppet::FileSystem::File.expects(:unlink).with(@public_key_path)
@searcher.destroy(@request)
end
it "should not fail if the public key does not exist when deleting the private key" do
- File.stubs(:unlink).with(@private_key_path)
+ Puppet::FileSystem::File.stubs(:unlink).with(@private_key_path)
- FileTest.stubs(:exist?).with(@private_key_path).returns true
- FileTest.expects(:exist?).with(@public_key_path).returns false
- File.expects(:unlink).with(@public_key_path).never
+ Puppet::FileSystem::File.stubs(:exist?).with(@private_key_path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@public_key_path).returns false
+ Puppet::FileSystem::File.expects(:unlink).with(@public_key_path).never
@searcher.destroy(@request)
end
diff --git a/spec/unit/indirector/resource/ral_spec.rb b/spec/unit/indirector/resource/ral_spec.rb
index 0e14a322b..8b42f6881 100755
--- a/spec/unit/indirector/resource/ral_spec.rb
+++ b/spec/unit/indirector/resource/ral_spec.rb
@@ -2,6 +2,13 @@
require 'spec_helper'
describe "Puppet::Resource::Ral" do
+
+ it "is deprecated on the network, but still allows requests" do
+ Puppet.expects(:deprecation_warning)
+
+ expect(Puppet::Resource::Ral.new.allow_remote_requests?).to eq(true)
+ end
+
describe "find" do
before do
@request = stub 'request', :key => "user/root"
diff --git a/spec/unit/indirector/resource/store_configs_spec.rb b/spec/unit/indirector/resource/store_configs_spec.rb
index aab2a4475..0ddb94470 100755
--- a/spec/unit/indirector/resource/store_configs_spec.rb
+++ b/spec/unit/indirector/resource/store_configs_spec.rb
@@ -9,4 +9,15 @@ end
describe Puppet::Resource::StoreConfigs do
it_should_behave_like "a StoreConfigs terminus"
+
+ before :each do
+ Puppet[:storeconfigs] = true
+ Puppet[:storeconfigs_backend] = "store_configs_testing"
+ end
+
+ it "is deprecated on the network, but still allows requests" do
+ Puppet.expects(:deprecation_warning)
+
+ expect(Puppet::Resource::StoreConfigs.new.allow_remote_requests?).to eq(true)
+ end
end
diff --git a/spec/unit/indirector/rest_spec.rb b/spec/unit/indirector/rest_spec.rb
index 787c4cb5e..0bf0bcb48 100755
--- a/spec/unit/indirector/rest_spec.rb
+++ b/spec/unit/indirector/rest_spec.rb
@@ -109,6 +109,10 @@ describe Puppet::Indirector::REST do
string.split(',').collect { |s| convert_from(format, s) }
end
+ def to_data_hash
+ { 'name' => @name, 'data' => @data }
+ end
+
def ==(other)
other.is_a? Puppet::TestModel and other.name == name and other.data == data
end
@@ -205,21 +209,21 @@ describe Puppet::Indirector::REST do
@request = stub 'request', :key => "foo", :server => nil, :port => nil
terminus.class.expects(:port).returns 321
terminus.class.expects(:server).returns "myserver"
- Puppet::Network::HTTP::Connection.expects(:new).with("myserver", 321).returns "myconn"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
terminus.network(@request).should == "myconn"
end
it "should use the server from the indirection request if one is present" do
@request = stub 'request', :key => "foo", :server => "myserver", :port => nil
terminus.class.stubs(:port).returns 321
- Puppet::Network::HTTP::Connection.expects(:new).with("myserver", 321).returns "myconn"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
terminus.network(@request).should == "myconn"
end
it "should use the port from the indirection request if one is present" do
@request = stub 'request', :key => "foo", :server => nil, :port => 321
terminus.class.stubs(:server).returns "myserver"
- Puppet::Network::HTTP::Connection.expects(:new).with("myserver", 321).returns "myconn"
+ Puppet::Network::HttpPool.expects(:http_instance).with("myserver", 321).returns "myconn"
terminus.network(@request).should == "myconn"
end
end
diff --git a/spec/unit/indirector/ssl_file_spec.rb b/spec/unit/indirector/ssl_file_spec.rb
index 4cc0e216f..8406cc9d7 100755
--- a/spec/unit/indirector/ssl_file_spec.rb
+++ b/spec/unit/indirector/ssl_file_spec.rb
@@ -121,9 +121,9 @@ describe Puppet::Indirector::SslFile do
describe "when finding certificates on disk" do
describe "and no certificate is present" do
it "should return nil" do
- FileTest.expects(:exist?).with(@path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns(true)
Dir.expects(:entries).with(@path).returns([])
- FileTest.expects(:exist?).with(@certpath).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with(@certpath).returns(false)
@searcher.find(@request).should be_nil
end
@@ -139,7 +139,7 @@ describe Puppet::Indirector::SslFile do
context "is readable" do
it "should return an instance of the model, which it should use to read the certificate" do
- FileTest.expects(:exist?).with(@certpath).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@certpath).returns true
model.expects(:new).with("myname").returns cert
cert.expects(:read).with(@certpath)
@@ -150,7 +150,7 @@ describe Puppet::Indirector::SslFile do
context "is unreadable" do
it "should raise an exception" do
- FileTest.expects(:exist?).with(@certpath).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(@certpath).returns(true)
model.expects(:new).with("myname").returns cert
cert.expects(:read).with(@certpath).raises(Errno::EACCES)
@@ -171,9 +171,9 @@ describe Puppet::Indirector::SslFile do
# the support for upper-case certs can be removed around mid-2009.
it "should rename the existing file to the lower-case path" do
@path = @searcher.path("myhost")
- FileTest.expects(:exist?).with(@path).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with(@path).returns(false)
dir, file = File.split(@path)
- FileTest.expects(:exist?).with(dir).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(dir).returns true
Dir.expects(:entries).with(dir).returns [".", "..", "something.pem", file.upcase]
File.expects(:rename).with(File.join(dir, file.upcase), @path)
@@ -221,7 +221,7 @@ describe Puppet::Indirector::SslFile do
@searcher.class.store_in @setting
fh = mock 'filehandle'
fh.stubs :print
- Puppet.settings.expects(:writesub).with(@setting, @certpath).yields fh
+ Puppet.settings.setting(@setting).expects(:open_file).with(@certpath, 'w').yields fh
@searcher.save(@request)
end
@@ -233,7 +233,7 @@ describe Puppet::Indirector::SslFile do
fh = mock 'filehandle'
fh.stubs :print
- Puppet.settings.expects(:write).with(@setting).yields fh
+ Puppet.settings.setting(@setting).expects(:open).with('w').yields fh
@searcher.save(@request)
end
end
@@ -246,7 +246,7 @@ describe Puppet::Indirector::SslFile do
fh = mock 'filehandle'
fh.stubs :print
- Puppet.settings.expects(:write).with(:cakey).yields fh
+ Puppet.settings.setting(:cakey).expects(:open).with('w').yields fh
@searcher.stubs(:ca?).returns true
@searcher.save(@request)
end
@@ -256,7 +256,7 @@ describe Puppet::Indirector::SslFile do
describe "when destroying certificates" do
describe "that do not exist" do
before do
- FileTest.expects(:exist?).with(@certpath).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@certpath).returns false
end
it "should return false" do
@@ -265,18 +265,15 @@ describe Puppet::Indirector::SslFile do
end
describe "that exist" do
- before do
- FileTest.expects(:exist?).with(@certpath).returns true
- end
-
it "should unlink the certificate file" do
- File.expects(:unlink).with(@certpath)
+ Puppet::FileSystem::File.expects(:exist?).with(@certpath).returns true
+ Puppet::FileSystem::File.expects(:unlink).with(@certpath)
@searcher.destroy(@request)
end
it "should log that is removing the file" do
- File.stubs(:exist?).returns true
- File.stubs(:unlink)
+ Puppet::FileSystem::File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:unlink)
Puppet.expects(:notice)
@searcher.destroy(@request)
end
diff --git a/spec/unit/indirector/yaml_spec.rb b/spec/unit/indirector/yaml_spec.rb
index 8a2753479..6830869b1 100755
--- a/spec/unit/indirector/yaml_spec.rb
+++ b/spec/unit/indirector/yaml_spec.rb
@@ -149,15 +149,15 @@ describe Puppet::Indirector::Yaml do
end
it "should unlink the right yaml file if it exists" do
- File.expects(:exists?).with(path).returns true
- File.expects(:unlink).with(path)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns true
+ Puppet::FileSystem::File.expects(:unlink).with(path)
@store.destroy(@request)
end
it "should not unlink the yaml file if it does not exists" do
- File.expects(:exists?).with(path).returns false
- File.expects(:unlink).with(path).never
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns false
+ Puppet::FileSystem::File.expects(:unlink).with(path).never
@store.destroy(@request)
end
diff --git a/spec/unit/module_spec.rb b/spec/unit/module_spec.rb
index c06f278eb..5c4065e14 100755
--- a/spec/unit/module_spec.rb
+++ b/spec/unit/module_spec.rb
@@ -15,7 +15,7 @@ describe Puppet::Module do
before do
# This is necessary because of the extra checks we have for the deprecated
# 'plugins' directory
- FileTest.stubs(:exist?).returns false
+ Puppet::FileSystem::File.stubs(:exist?).returns false
end
it "should have a class method that returns a named module from a given environment" do
@@ -90,12 +90,14 @@ describe Puppet::Module do
describe "when finding unmet dependencies" do
before do
- FileTest.unstub(:exist?)
+ Puppet::FileSystem::File.unstub(:exist?)
@modpath = tmpdir('modpath')
Puppet.settings[:modulepath] = @modpath
end
it "should list modules that are missing" do
+ metadata_file = "#{@modpath}/needy/metadata.json"
+ Puppet::FileSystem::File.expects(:exist?).twice.with(metadata_file).returns true
mod = PuppetSpec::Modules.create(
'needy',
@modpath,
@@ -116,6 +118,8 @@ describe Puppet::Module do
end
it "should list modules that are missing and have invalid names" do
+ metadata_file = "#{@modpath}/needy/metadata.json"
+ Puppet::FileSystem::File.expects(:exist?).with(metadata_file).twice.returns true
mod = PuppetSpec::Modules.create(
'needy',
@modpath,
@@ -136,6 +140,10 @@ describe Puppet::Module do
end
it "should list modules with unmet version requirement" do
+ ['foobar', 'foobaz'].each do |mod_name|
+ metadata_file = "#{@modpath}/#{mod_name}/metadata.json"
+ Puppet::FileSystem::File.stubs(:exist?).with(metadata_file).returns true
+ end
mod = PuppetSpec::Modules.create(
'foobar',
@modpath,
@@ -204,6 +212,8 @@ describe Puppet::Module do
end
it "should consider a dependency without a semantic version to be unmet" do
+ metadata_file = "#{@modpath}/foobar/metadata.json"
+ Puppet::FileSystem::File.expects(:exist?).with(metadata_file).times(3).returns true
mod = PuppetSpec::Modules.create(
'foobar',
@modpath,
@@ -244,6 +254,10 @@ describe Puppet::Module do
end
it "should only list unmet dependencies" do
+ [name, 'satisfied'].each do |mod_name|
+ metadata_file = "#{@modpath}/#{mod_name}/metadata.json"
+ Puppet::FileSystem::File.expects(:exist?).with(metadata_file).twice.returns true
+ end
mod = PuppetSpec::Modules.create(
name,
@modpath,
@@ -357,35 +371,42 @@ describe Puppet::Module do
end
end
- [:plugins, :templates, :files, :manifests].each do |filetype|
- dirname = filetype == :plugins ? "lib" : filetype.to_s
+ [:plugins, :pluginfacts, :templates, :files, :manifests].each do |filetype|
+ case filetype
+ when :plugins
+ dirname = "lib"
+ when :pluginfacts
+ dirname = "facts.d"
+ else
+ dirname = filetype.to_s
+ end
it "should be able to return individual #{filetype}" do
module_file = File.join(path, dirname, "my/file")
- FileTest.expects(:exist?).with(module_file).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(module_file).returns true
mod.send(filetype.to_s.sub(/s$/, ''), "my/file").should == module_file
end
it "should consider #{filetype} to be present if their base directory exists" do
module_file = File.join(path, dirname)
- FileTest.expects(:exist?).with(module_file).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(module_file).returns true
mod.send(filetype.to_s + "?").should be_true
end
it "should consider #{filetype} to be absent if their base directory does not exist" do
module_file = File.join(path, dirname)
- FileTest.expects(:exist?).with(module_file).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(module_file).returns false
mod.send(filetype.to_s + "?").should be_false
end
it "should return nil if asked to return individual #{filetype} that don't exist" do
module_file = File.join(path, dirname, "my/file")
- FileTest.expects(:exist?).with(module_file).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(module_file).returns false
mod.send(filetype.to_s.sub(/s$/, ''), "my/file").should be_nil
end
it "should return the base directory if asked for a nil path" do
base = File.join(path, dirname)
- FileTest.expects(:exist?).with(base).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(base).returns true
mod.send(filetype.to_s.sub(/s$/, ''), nil).should == base
end
end
@@ -418,8 +439,8 @@ describe Puppet::Module, "when finding matching manifests" do
end
it "should default to the 'init' file if no glob pattern is specified" do
- FileTest.expects(:exist?).with("/a/manifests/init.pp").returns(true)
- FileTest.expects(:exist?).with("/a/manifests/init.rb").returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with("/a/manifests/init.pp").returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with("/a/manifests/init.rb").returns(false)
@mod.match_manifests(nil).should == %w{/a/manifests/init.pp}
end
@@ -471,21 +492,21 @@ describe Puppet::Module do
end
it "should have metadata if it has a metadata file and its data is not empty" do
- FileTest.expects(:exist?).with(@module.metadata_file).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@module.metadata_file).returns true
File.stubs(:read).with(@module.metadata_file).returns "{\"foo\" : \"bar\"}"
@module.should be_has_metadata
end
it "should have metadata if it has a metadata file and its data is not empty" do
- FileTest.expects(:exist?).with(@module.metadata_file).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@module.metadata_file).returns true
File.stubs(:read).with(@module.metadata_file).returns "{\"foo\" : \"bar\"}"
@module.should be_has_metadata
end
it "should not have metadata if has a metadata file and its data is empty" do
- FileTest.expects(:exist?).with(@module.metadata_file).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@module.metadata_file).returns true
File.stubs(:read).with(@module.metadata_file).returns "/*
+-----------------------------------------------------------------------+
| |
@@ -503,7 +524,7 @@ describe Puppet::Module do
end
it "should know if it is missing a metadata file" do
- FileTest.expects(:exist?).with(@module.metadata_file).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@module.metadata_file).returns false
@module.should_not be_has_metadata
end
@@ -519,6 +540,13 @@ describe Puppet::Module do
Puppet::Module.new("yay", "/path", mock("env"))
end
+ it "should tolerate failure to parse" do
+ Puppet::FileSystem::File.expects(:exist?).with(@module.metadata_file).returns true
+ File.stubs(:read).with(@module.metadata_file).returns(my_fixture('trailing-comma.json'))
+
+ @module.has_metadata?.should be_false
+ end
+
def a_module_with_metadata(data)
text = data.to_pson
diff --git a/spec/unit/module_tool/tar/gnu_spec.rb b/spec/unit/module_tool/tar/gnu_spec.rb
index b5fc78918..93245da1a 100644
--- a/spec/unit/module_tool/tar/gnu_spec.rb
+++ b/spec/unit/module_tool/tar/gnu_spec.rb
@@ -8,9 +8,9 @@ describe Puppet::ModuleTool::Tar::Gnu do
let(:destfile) { '/the/dest/file.tar.gz' }
it "unpacks a tar file" do
- Puppet::Util::Execution.expects(:execute).with("tar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
+ Puppet::Util::Execution.expects(:execute).with("tar xzf #{sourcefile} --no-same-owner -C #{destdir}")
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type d -exec chmod 755 {} +")
- Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod 644 {} +")
+ Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod a-wst {} +")
Puppet::Util::Execution.expects(:execute).with("chown -R <owner:group> #{destdir}")
subject.unpack(sourcefile, destdir, '<owner:group>')
end
diff --git a/spec/unit/module_tool/tar/solaris_spec.rb b/spec/unit/module_tool/tar/solaris_spec.rb
index 23bbd8d20..1ca7a6a09 100644
--- a/spec/unit/module_tool/tar/solaris_spec.rb
+++ b/spec/unit/module_tool/tar/solaris_spec.rb
@@ -8,9 +8,9 @@ describe Puppet::ModuleTool::Tar::Solaris do
let(:destfile) { '/the/dest/file.tar.gz' }
it "unpacks a tar file" do
- Puppet::Util::Execution.expects(:execute).with("gtar xzf #{sourcefile} --no-same-permissions --no-same-owner -C #{destdir}")
+ Puppet::Util::Execution.expects(:execute).with("gtar xzf #{sourcefile} --no-same-owner -C #{destdir}")
Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type d -exec chmod 755 {} +")
- Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod 644 {} +")
+ Puppet::Util::Execution.expects(:execute).with("find #{destdir} -type f -exec chmod a-wst {} +")
Puppet::Util::Execution.expects(:execute).with("chown -R <owner:group> #{destdir}")
subject.unpack(sourcefile, destdir, '<owner:group>')
end
diff --git a/spec/unit/module_tool/tar_spec.rb b/spec/unit/module_tool/tar_spec.rb
new file mode 100644
index 000000000..3de0dda48
--- /dev/null
+++ b/spec/unit/module_tool/tar_spec.rb
@@ -0,0 +1,45 @@
+require 'spec_helper'
+require 'puppet/module_tool/tar'
+
+describe Puppet::ModuleTool::Tar do
+
+ it "uses gtar when present on Solaris" do
+ Facter.stubs(:value).with('osfamily').returns 'Solaris'
+ Puppet::Util.stubs(:which).with('gtar').returns '/usr/bin/gtar'
+
+ described_class.instance(nil).should be_a_kind_of Puppet::ModuleTool::Tar::Solaris
+ end
+
+ it "uses gtar when present on OpenBSD" do
+ Facter.stubs(:value).with('osfamily').returns 'OpenBSD'
+ Puppet::Util.stubs(:which).with('gtar').returns '/usr/bin/gtar'
+
+ described_class.instance(nil).should be_a_kind_of Puppet::ModuleTool::Tar::Solaris
+ end
+
+ it "uses tar when present and not on Windows" do
+ Facter.stubs(:value).with('osfamily').returns 'ObscureLinuxDistro'
+ Puppet::Util.stubs(:which).with('tar').returns '/usr/bin/tar'
+ Puppet::Util::Platform.stubs(:windows?).returns false
+
+ described_class.instance(nil).should be_a_kind_of Puppet::ModuleTool::Tar::Gnu
+ end
+
+ it "falls back to minitar when it and zlib are present" do
+ Facter.stubs(:value).with('osfamily').returns 'Windows'
+ Puppet::Util.stubs(:which).with('tar')
+ Puppet::Util::Platform.stubs(:windows?).returns true
+ Puppet.stubs(:features).returns(stub(:minitar? => true, :zlib? => true))
+
+ described_class.instance(nil).should be_a_kind_of Puppet::ModuleTool::Tar::Mini
+ end
+
+ it "fails when there is no possible implementation" do
+ Facter.stubs(:value).with('osfamily').returns 'Windows'
+ Puppet::Util.stubs(:which).with('tar')
+ Puppet::Util::Platform.stubs(:windows?).returns true
+ Puppet.stubs(:features).returns(stub(:minitar? => false, :zlib? => false))
+
+ expect { described_class.instance(nil) }.to raise_error RuntimeError, /No suitable tar/
+ end
+end
diff --git a/spec/unit/network/authconfig_spec.rb b/spec/unit/network/authconfig_spec.rb
index 6814b2c1b..be45152c0 100755
--- a/spec/unit/network/authconfig_spec.rb
+++ b/spec/unit/network/authconfig_spec.rb
@@ -5,7 +5,8 @@ require 'puppet/network/authconfig'
describe Puppet::Network::AuthConfig do
before :each do
- File.stubs(:stat).returns(stub('stat', :ctime => :now))
+ stub_file = stub('file', :stat => stub('stat', :ctime => :now))
+ Puppet::FileSystem::File.stubs(:new).returns stub_file
Time.stubs(:now).returns Time.now
Puppet::Network::AuthConfig.any_instance.stubs(:exists?).returns(true)
diff --git a/spec/unit/network/authentication_spec.rb b/spec/unit/network/authentication_spec.rb
index 5b54757b8..c18552ab8 100755
--- a/spec/unit/network/authentication_spec.rb
+++ b/spec/unit/network/authentication_spec.rb
@@ -20,7 +20,7 @@ describe Puppet::Network::Authentication do
describe "when warning about upcoming expirations" do
before do
Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(false)
- FileTest.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
end
it "should check the expiration of the CA certificate" do
@@ -34,7 +34,7 @@ describe Puppet::Network::Authentication do
it "should check the expiration of the localhost certificate" do
Puppet::SSL::Host.stubs(:localhost).returns(host)
cert.expects(:near_expiration?).returns(false)
- FileTest.stubs(:exist?).with(Puppet[:hostcert]).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(Puppet[:hostcert]).returns(true)
subject.warn_if_near_expiration
end
diff --git a/spec/unit/network/format_handler_spec.rb b/spec/unit/network/format_handler_spec.rb
index b8ab39634..1716a7296 100755
--- a/spec/unit/network/format_handler_spec.rb
+++ b/spec/unit/network/format_handler_spec.rb
@@ -63,8 +63,8 @@ describe Puppet::Network::FormatHandler do
Puppet::Network::FormatHandler.most_suitable_format_for(accepted, [:one, :two])
end
- it "finds either format when anything is accepted" do
- [format_one, format_two].should include(suitable_in_setup_formats(["*/*"]))
+ it "finds the most preferred format when anything is acceptable" do
+ Puppet::Network::FormatHandler.most_suitable_format_for(["*/*"], [:two, :one]).should == format_two
end
it "finds no format when none are acceptable" do
diff --git a/spec/unit/network/formats_spec.rb b/spec/unit/network/formats_spec.rb
index 8531a541a..57ff77795 100755
--- a/spec/unit/network/formats_spec.rb
+++ b/spec/unit/network/formats_spec.rb
@@ -26,6 +26,30 @@ class PsonTest
end
describe "Puppet Network Format" do
+ it "should include a msgpack format", :if => Puppet.features.msgpack? do
+ Puppet::Network::FormatHandler.format(:msgpack).should_not be_nil
+ end
+
+ describe "msgpack", :if => Puppet.features.msgpack? do
+ before do
+ @msgpack = Puppet::Network::FormatHandler.format(:msgpack)
+ end
+
+ it "should have its mime type set to application/x-msgpack" do
+ @msgpack.mime.should == "application/x-msgpack"
+ end
+
+ it "should have a weight of 20" do
+ @msgpack.weight.should == 20
+ end
+
+ it "should fail when one element does not have a from_pson" do
+ expect do
+ @msgpack.intern_multiple(Hash, MessagePack.pack(["foo"]))
+ end.to raise_error(NoMethodError)
+ end
+ end
+
it "should include a yaml format" do
Puppet::Network::FormatHandler.format(:yaml).should_not be_nil
end
diff --git a/spec/unit/network/http/connection_spec.rb b/spec/unit/network/http/connection_spec.rb
index 0d6da0671..467705f01 100644
--- a/spec/unit/network/http/connection_spec.rb
+++ b/spec/unit/network/http/connection_spec.rb
@@ -7,19 +7,13 @@ describe Puppet::Network::HTTP::Connection do
let (:host) { "me" }
let (:port) { 54321 }
- subject { Puppet::Network::HTTP::Connection.new(host, port) }
+ subject { Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator) }
context "when providing HTTP connections" do
after do
Puppet::Network::HTTP::Connection.instance_variable_set("@ssl_host", nil)
end
- it "should use the global SSL::Host instance to get its certificate information" do
- host = mock 'host'
- Puppet::SSL::Host.expects(:localhost).with.returns host
- subject.send(:ssl_host).should equal(host)
- end
-
context "when initializing http instances" do
before :each do
# All of the cert stuff is tested elsewhere
@@ -39,51 +33,12 @@ describe Puppet::Network::HTTP::Connection do
end
it "can set ssl using an option" do
- Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false).send(:connection).should_not be_use_ssl
- Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true).send(:connection).should be_use_ssl
- end
-
- describe "peer verification" do
- def setup_standard_ssl_configuration
- ca_cert_file = File.expand_path('/path/to/ssl/certs/ca_cert.pem')
- FileTest.stubs(:exist?).with(ca_cert_file).returns(true)
-
- ssl_configuration = stub('ssl_configuration', :ca_auth_file => ca_cert_file)
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_configuration).returns(ssl_configuration)
- end
-
- def setup_standard_hostcert
- host_cert_file = File.expand_path('/path/to/ssl/certs/host_cert.pem')
- FileTest.stubs(:exist?).with(host_cert_file).returns(true)
-
- Puppet[:hostcert] = host_cert_file
- end
-
- def setup_standard_ssl_host
- cert = stub('cert', :content => 'real_cert')
- key = stub('key', :content => 'real_key')
- host = stub('host', :certificate => cert, :key => key, :ssl_store => stub('store'))
-
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_host).returns(host)
- end
-
- before do
- setup_standard_ssl_configuration
- setup_standard_hostcert
- setup_standard_ssl_host
- end
-
- it "can enable peer verification" do
- Puppet::Network::HTTP::Connection.new(host, port, :verify_peer => true).send(:connection).verify_mode.should == OpenSSL::SSL::VERIFY_PEER
- end
-
- it "can disable peer verification" do
- Puppet::Network::HTTP::Connection.new(host, port, :verify_peer => false).send(:connection).verify_mode.should == OpenSSL::SSL::VERIFY_NONE
- end
+ Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator).send(:connection).should_not be_use_ssl
+ Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true, :verify => Puppet::SSL::Validator.no_validator).send(:connection).should be_use_ssl
end
context "proxy and timeout settings should propagate" do
- subject { Puppet::Network::HTTP::Connection.new(host, port).send(:connection) }
+ subject { Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator).send(:connection) }
before :each do
Puppet[:http_proxy_host] = "myhost"
Puppet[:http_proxy_port] = 432
@@ -104,94 +59,13 @@ describe Puppet::Network::HTTP::Connection do
it "should raise Puppet::Error when invalid options are specified" do
expect { Puppet::Network::HTTP::Connection.new(host, port, :invalid_option => nil) }.to raise_error(Puppet::Error, 'Unrecognized option(s): :invalid_option')
end
-
- end
-
- describe "when doing SSL setup for http instances" do
- let :store do stub('store') end
-
- let :ca_auth_file do
- '/path/to/ssl/certs/ssl_server_ca_auth.pem'
- end
-
- let :ssl_configuration do
- stub('ssl_configuration', :ca_auth_file => ca_auth_file)
- end
-
- before :each do
- Puppet[:hostcert] = '/host/cert'
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_configuration).returns(ssl_configuration)
-
- cert = stub 'cert', :content => 'real_cert'
- key = stub 'key', :content => 'real_key'
- host = stub 'host', :certificate => cert, :key => key, :ssl_store => store
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_host).returns(host)
- end
-
- shared_examples "HTTPS setup without all certificates" do
- subject { Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true).send(:connection) }
-
- it { should be_use_ssl }
- its(:cert) { should be_nil }
- its(:ca_file) { should be_nil }
- its(:key) { should be_nil }
- its(:verify_mode) { should == OpenSSL::SSL::VERIFY_NONE }
- end
-
- context "with neither a host cert or a local CA cert" do
- before :each do
- FileTest.stubs(:exist?).with(Puppet[:hostcert]).returns(false)
- FileTest.stubs(:exist?).with(ca_auth_file).returns(false)
- end
-
- include_examples "HTTPS setup without all certificates"
- end
-
- context "with there is no host certificate" do
- before :each do
- FileTest.stubs(:exist?).with(Puppet[:hostcert]).returns(false)
- FileTest.stubs(:exist?).with(ca_auth_file).returns(true)
- end
-
- include_examples "HTTPS setup without all certificates"
- end
-
- context "with there is no local CA certificate" do
- before :each do
- FileTest.stubs(:exist?).with(Puppet[:hostcert]).returns(true)
- FileTest.stubs(:exist?).with(ca_auth_file).returns(false)
- end
-
- include_examples "HTTPS setup without all certificates"
- end
-
- context "with both the host and CA cert" do
- subject { Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true).send(:connection) }
-
- before :each do
- FileTest.expects(:exist?).with(Puppet[:hostcert]).returns(true)
- FileTest.expects(:exist?).with(ca_auth_file).returns(true)
- end
-
- it { should be_use_ssl }
- its(:cert_store) { should equal store }
- its(:cert) { should == "real_cert" }
- its(:key) { should == "real_key" }
- its(:verify_mode) { should == OpenSSL::SSL::VERIFY_PEER }
- its(:ca_file) { should == ca_auth_file }
- end
-
- it "should set up certificate information when creating http instances" do
- subject.expects(:cert_setup)
- subject.send(:connection)
- end
end
end
context "when methods that accept a block are called with a block" do
let (:host) { "my_server" }
let (:port) { 8140 }
- let (:subject) { Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false) }
+ let (:subject) { Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator) }
let (:httpok) { Net::HTTPOK.new('1.1', 200, '') }
before :each do
@@ -228,95 +102,99 @@ describe Puppet::Network::HTTP::Connection do
let (:host) { "my_server" }
let (:port) { 8140 }
let (:httpok) { Net::HTTPOK.new('1.1', 200, '') }
- let (:subject) { Puppet::Network::HTTP::Connection.new(host, port) }
-
- def a_connection_that_verifies(args)
- connection = Net::HTTP.new(host, port)
- connection.stubs(:warn_if_near_expiration)
- connection.stubs(:get).with do
- connection.verify_callback.call(args[:has_passed_pre_checks], args[:in_context])
- true
- end.raises(OpenSSL::SSL::SSLError.new(args[:fails_with]))
- connection
- end
-
- def a_store_context(args)
- Puppet[:confdir] = tmpdir('conf')
- ssl_context = mock('OpenSSL::X509::StoreContext')
- if args[:verify_raises]
- ssl_context.stubs(:current_cert).raises("oh noes")
- else
- cert = Puppet::SSL::CertificateAuthority.new.generate(args[:for_server], :dns_alt_names => args[:for_aliases]).content
- ssl_context.stubs(:current_cert).returns(cert)
- end
- ssl_context.stubs(:chain).returns([])
- ssl_context.stubs(:error_string).returns(args[:with_error_string])
- ssl_context
- end
it "should provide a useful error message when one is available and certificate validation fails", :unless => Puppet.features.microsoft_windows? do
- subject.stubs(:create_connection).
- returns(a_connection_that_verifies(:has_passed_pre_checks => false,
- :in_context => a_store_context(:for_server => 'not_my_server',
- :with_error_string => 'shady looking signature'),
- :fails_with => 'certificate verify failed'))
- expect do
- subject.request(:get, stub('request'))
- end.to raise_error(Puppet::Error, "certificate verify failed: [shady looking signature for /CN=not_my_server]")
- end
+ connection = Puppet::Network::HTTP::Connection.new(
+ host, port,
+ :verify => ConstantErrorValidator.new(:fails_with => 'certificate verify failed',
+ :error_string => 'shady looking signature'))
- it "should provide a useful error message when verify_callback raises", :unless => Puppet.features.microsoft_windows? do
- subject.stubs(:create_connection).
- returns(a_connection_that_verifies(:has_passed_pre_checks => false,
- :in_context => a_store_context(:verify_raises => true),
- :fails_with => 'certificate verify failed'))
expect do
- subject.request(:get, stub('request'))
- end.to raise_error(Puppet::Error, "certificate verify failed: [oh noes]")
+ connection.get('request')
+ end.to raise_error(Puppet::Error, "certificate verify failed: [shady looking signature]")
end
it "should provide a helpful error message when hostname was not match with server certificate", :unless => Puppet.features.microsoft_windows? do
- subject.stubs(:create_connection).
- returns(a_connection_that_verifies(:has_passed_pre_checks => true,
- :in_context => a_store_context(:for_server => 'not_my_server',
- :for_aliases => 'foo,bar,baz'),
- :fails_with => 'hostname was not match with server certificate'))
-
- expect { subject.request(:get, stub('request')) }.
- to raise_error(Puppet::Error) do |error|
+ Puppet[:confdir] = tmpdir('conf')
+
+ connection = Puppet::Network::HTTP::Connection.new(
+ host, port,
+ :verify => ConstantErrorValidator.new(
+ :fails_with => 'hostname was not match with server certificate',
+ :peer_certs => [Puppet::SSL::CertificateAuthority.new.generate(
+ 'not_my_server', :dns_alt_names => 'foo,bar,baz')]))
+
+ expect do
+ connection.get('request')
+ end.to raise_error(Puppet::Error) do |error|
error.message =~ /Server hostname 'my_server' did not match server certificate; expected one of (.+)/
$1.split(', ').should =~ %w[DNS:foo DNS:bar DNS:baz DNS:not_my_server not_my_server]
end
end
it "should pass along the error message otherwise" do
- connection = Net::HTTP.new('my_server', 8140)
- subject.stubs(:create_connection).returns(connection)
-
- connection.stubs(:get).raises(OpenSSL::SSL::SSLError.new('some other message'))
+ connection = Puppet::Network::HTTP::Connection.new(
+ host, port,
+ :verify => ConstantErrorValidator.new(:fails_with => 'some other message'))
expect do
- subject.request(:get, stub('request'))
+ connection.get('request')
end.to raise_error(/some other message/)
end
it "should check all peer certificates for upcoming expiration", :unless => Puppet.features.microsoft_windows? do
- connection = Net::HTTP.new('my_server', 8140)
- subject.stubs(:create_connection).returns(connection)
+ Puppet[:confdir] = tmpdir('conf')
+ cert = Puppet::SSL::CertificateAuthority.new.generate(
+ 'server', :dns_alt_names => 'foo,bar,baz')
+
+ connection = Puppet::Network::HTTP::Connection.new(
+ host, port,
+ :verify => NoProblemsValidator.new(cert))
- cert = stubs 'cert'
- Puppet::SSL::Certificate.expects(:from_instance).twice.returns(cert)
+ Net::HTTP.any_instance.stubs(:get).returns(httpok)
- connection.stubs(:get).with do
- context = a_store_context(:for_server => 'a_server', :with_error_string => false)
- connection.verify_callback.call(true, context)
- connection.verify_callback.call(true, context)
- true
- end.returns(httpok)
+ connection.expects(:warn_if_near_expiration).with(cert)
- subject.expects(:warn_if_near_expiration).with(cert, cert)
+ connection.get('request')
+ end
+
+ class ConstantErrorValidator
+ def initialize(args)
+ @fails_with = args[:fails_with]
+ @error_string = args[:error_string] || ""
+ @peer_certs = args[:peer_certs] || []
+ end
- subject.request(:get, stubs('request'))
+ def setup_connection(connection)
+ connection.stubs(:get).with do
+ true
+ end.raises(OpenSSL::SSL::SSLError.new(@fails_with))
+ end
+
+ def peer_certs
+ @peer_certs
+ end
+
+ def verify_errors
+ [@error_string]
+ end
+ end
+
+ class NoProblemsValidator
+ def initialize(cert)
+ @cert = cert
+ end
+
+ def setup_connection(connection)
+ end
+
+ def peer_certs
+ [@cert]
+ end
+
+ def verify_errors
+ []
+ end
end
end
@@ -324,7 +202,7 @@ describe Puppet::Network::HTTP::Connection do
let (:other_host) { "redirected" }
let (:other_port) { 9292 }
let (:other_path) { "other-path" }
- let (:subject) { Puppet::Network::HTTP::Connection.new("my_server", 8140, :use_ssl => false) }
+ let (:subject) { Puppet::Network::HTTP::Connection.new("my_server", 8140, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator) }
let (:httpredirection) { Net::HTTPFound.new('1.1', 302, 'Moved Temporarily') }
let (:httpok) { Net::HTTPOK.new('1.1', 200, '') }
@@ -356,5 +234,4 @@ describe Puppet::Network::HTTP::Connection do
}.to raise_error(Puppet::Network::HTTP::RedirectionLimitExceededException)
end
end
-
end
diff --git a/spec/unit/network/http/handler_spec.rb b/spec/unit/network/http/handler_spec.rb
index 0ff087b02..53da5be01 100755
--- a/spec/unit/network/http/handler_spec.rb
+++ b/spec/unit/network/http/handler_spec.rb
@@ -38,6 +38,9 @@ describe Puppet::Network::HTTP::Handler do
end
class Puppet::TestModel::Memory < Puppet::Indirector::Memory
+ def supports_remote_requests?
+ true
+ end
end
Puppet::TestModel.indirection.terminus_class = :memory
@@ -150,9 +153,7 @@ describe Puppet::Network::HTTP::Handler do
describe "when processing a request" do
let(:response) do
- obj = stub "http 200 ok"
- obj.stubs(:[]=).with(Puppet::Network::HTTP::HEADER_PUPPET_VERSION, Puppet.version)
- obj
+ { :status => 200 }
end
before do
@@ -163,7 +164,6 @@ describe Puppet::Network::HTTP::Handler do
it "should check the client certificate for upcoming expiration" do
request = a_request
cert = mock 'cert'
- handler.stubs(:uri2indirection).returns(["facts", :mymethod, "key", {:node => "name"}])
handler.expects(:client_cert).returns(cert).with(request)
handler.expects(:warn_if_near_expiration).with(cert)
@@ -201,33 +201,31 @@ describe Puppet::Network::HTTP::Handler do
handler.process(request, response)
end
- it "should call the 'do' method and delegate authorization to the authorization layer" do
+ it "should return 403 if the request is not authorized" do
request = a_request
handler.expects(:uri2indirection).returns(["facts", :mymethod, "key", {:node => "name"}])
- handler.expects(:do_mymethod).with("facts", "key", {:node => "name"}, request, response)
+ handler.expects(:do_mymethod).never
+
+ handler.expects(:check_authorization).with("facts", :mymethod, "key", {:node => "name"}).raises(Puppet::Network::AuthorizationError.new("forbidden"))
- handler.expects(:check_authorization).with("facts", :mymethod, "key", {:node => "name"})
+ handler.expects(:set_response).with(anything, anything, 403)
handler.process(request, response)
end
- it "should return 403 if the request is not authorized" do
+ it "should return an error code if the indirection does not support remote requests" do
request = a_request
- handler.expects(:uri2indirection).returns(["facts", :mymethod, "key", {:node => "name"}])
- handler.expects(:do_mymethod).never
-
- handler.expects(:check_authorization).with("facts", :mymethod, "key", {:node => "name"}).raises(Puppet::Network::AuthorizationError.new("forbidden"))
-
- handler.expects(:set_response).with(anything, anything, 403)
+ indirection.expects(:allow_remote_requests?).returns(false)
handler.process(request, response)
+
+ expect(response[:status]).to eq 404
end
it "should serialize a controller exception when an exception is thrown while finding the model instance" do
- request = a_request
- handler.expects(:uri2indirection).returns(["facts", :find, "key", {:node => "name"}])
+ request = a_request_that_finds(Puppet::TestModel.new("key"))
handler.expects(:do_find).raises(ArgumentError, "The exception")
handler.expects(:set_response).with(anything, "The exception", 400)
@@ -302,7 +300,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data.render(:pson))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_find(indirection.name, "my data", {}, request, response)
+ handler.do_find(indirection, "my data", {}, request, response)
end
it "responds with a 406 error when no accept header is provided" do
@@ -311,7 +309,7 @@ describe Puppet::Network::HTTP::Handler do
request = a_request_that_finds(data, :accept_header => nil)
expect do
- handler.do_find(indirection.name, "my data", {}, request, response)
+ handler.do_find(indirection, "my data", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotAcceptableError)
end
@@ -321,7 +319,7 @@ describe Puppet::Network::HTTP::Handler do
request = a_request_that_finds(data, :accept_header => "unknown, also/unknown")
expect do
- handler.do_find(indirection.name, "my data", {}, request, response)
+ handler.do_find(indirection, "my data", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotAcceptableError)
end
@@ -334,7 +332,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data_string)
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_find(indirection.name, "my data", {}, request, response)
+ handler.do_find(indirection, "my data", {}, request, response)
end
it "should return a 404 when no model instance can be found" do
@@ -342,7 +340,7 @@ describe Puppet::Network::HTTP::Handler do
request = a_request_that_finds(data, :accept_header => "unknown, pson, yaml")
expect do
- handler.do_find(indirection.name, "my data", {}, request, response)
+ handler.do_find(indirection, "my data", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotFoundError)
end
end
@@ -377,7 +375,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, Puppet::TestModel.render_multiple(:pson, [data]))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_search(indirection.name, "my", {}, request, response)
+ handler.do_search(indirection, "my", {}, request, response)
end
it "should return [] when searching returns an empty array" do
@@ -386,7 +384,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, Puppet::TestModel.render_multiple(:pson, []))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_search(indirection.name, "nothing", {}, request, response)
+ handler.do_search(indirection, "nothing", {}, request, response)
end
it "should return a 404 when searching returns nil" do
@@ -394,7 +392,7 @@ describe Puppet::Network::HTTP::Handler do
indirection.expects(:search).returns(nil)
expect do
- handler.do_search(indirection.name, "nothing", {}, request, response)
+ handler.do_search(indirection, "nothing", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotFoundError)
end
end
@@ -405,7 +403,7 @@ describe Puppet::Network::HTTP::Handler do
indirection.save(data, "my data")
request = a_request_that_destroys(data)
- handler.do_destroy(indirection.name, "my data", {}, request, response)
+ handler.do_destroy(indirection, "my data", {}, request, response)
Puppet::TestModel.indirection.find("my data").should be_nil
end
@@ -418,7 +416,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data.render(:yaml))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:yaml))
- handler.do_destroy(indirection.name, "my data", {}, request, response)
+ handler.do_destroy(indirection, "my data", {}, request, response)
end
it "uses the first supported format for the response" do
@@ -429,7 +427,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data.render(:pson))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_destroy(indirection.name, "my data", {}, request, response)
+ handler.do_destroy(indirection, "my data", {}, request, response)
end
it "raises an error and does not destory when no accepted formats are known" do
@@ -438,7 +436,7 @@ describe Puppet::Network::HTTP::Handler do
request = a_request_that_submits(data, :accept_header => "unknown, also/unknown")
expect do
- handler.do_destroy(indirection.name, "my data", {}, request, response)
+ handler.do_destroy(indirection, "my data", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotAcceptableError)
Puppet::TestModel.indirection.find("my data").should_not be_nil
@@ -460,7 +458,7 @@ describe Puppet::Network::HTTP::Handler do
request[:content_type_header] = "application/x-raw"
request[:body] = ''
- handler.do_save(indirection.name, "test", {}, request, response)
+ handler.do_save(indirection, "test", {}, request, response)
Puppet::TestModel.indirection.find("test").data.should == ''
end
@@ -469,7 +467,7 @@ describe Puppet::Network::HTTP::Handler do
data = Puppet::TestModel.new("my data", "some data")
request = a_request_that_submits(data)
- handler.do_save(indirection.name, "my data", {}, request, response)
+ handler.do_save(indirection, "my data", {}, request, response)
Puppet::TestModel.indirection.find("my data").should == data
end
@@ -481,7 +479,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data.render(:yaml))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:yaml))
- handler.do_save(indirection.name, "my data", {}, request, response)
+ handler.do_save(indirection, "my data", {}, request, response)
end
it "uses the first supported format for the response" do
@@ -491,7 +489,7 @@ describe Puppet::Network::HTTP::Handler do
handler.expects(:set_response).with(response, data.render(:pson))
handler.expects(:set_content_type).with(response, Puppet::Network::FormatHandler.format(:pson))
- handler.do_save(indirection.name, "my data", {}, request, response)
+ handler.do_save(indirection, "my data", {}, request, response)
end
it "raises an error and does not save when no accepted formats are known" do
@@ -499,7 +497,7 @@ describe Puppet::Network::HTTP::Handler do
request = a_request_that_submits(data, :accept_header => "unknown, also/unknown")
expect do
- handler.do_save(indirection.name, "my data", {}, request, response)
+ handler.do_save(indirection, "my data", {}, request, response)
end.to raise_error(Puppet::Network::HTTP::Handler::HTTPNotAcceptableError)
Puppet::TestModel.indirection.find("my data").should be_nil
@@ -543,7 +541,8 @@ describe Puppet::Network::HTTP::Handler do
end
def set_response(response, body, status = 200)
- "my_result"
+ response[:body] = body
+ response[:status] = status
end
def http_method(request)
diff --git a/spec/unit/network/http_pool_spec.rb b/spec/unit/network/http_pool_spec.rb
index c671e88f1..4ee507568 100755
--- a/spec/unit/network/http_pool_spec.rb
+++ b/spec/unit/network/http_pool_spec.rb
@@ -3,6 +3,10 @@ require 'spec_helper'
require 'puppet/network/http_pool'
describe Puppet::Network::HttpPool do
+ before :each do
+ Puppet::SSL::Key.indirection.terminus_class = :memory
+ Puppet::SSL::CertificateRequest.indirection.terminus_class = :memory
+ end
describe "when managing http instances" do
@@ -26,15 +30,14 @@ describe Puppet::Network::HttpPool do
describe 'peer verification' do
def setup_standard_ssl_configuration
ca_cert_file = File.expand_path('/path/to/ssl/certs/ca_cert.pem')
- FileTest.stubs(:exist?).with(ca_cert_file).returns(true)
- ssl_configuration = stub('ssl_configuration', :ca_auth_file => ca_cert_file)
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_configuration).returns(ssl_configuration)
+ Puppet[:ssl_client_ca_auth] = ca_cert_file
+ Puppet::FileSystem::File.stubs(:exist?).with(ca_cert_file).returns(true)
end
def setup_standard_hostcert
host_cert_file = File.expand_path('/path/to/ssl/certs/host_cert.pem')
- FileTest.stubs(:exist?).with(host_cert_file).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(host_cert_file).returns(true)
Puppet[:hostcert] = host_cert_file
end
@@ -44,7 +47,7 @@ describe Puppet::Network::HttpPool do
key = stub('key', :content => 'real_key')
host = stub('host', :certificate => cert, :key => key, :ssl_store => stub('store'))
- Puppet::Network::HTTP::Connection.any_instance.stubs(:ssl_host).returns(host)
+ Puppet::SSL::Host.stubs(:localhost).returns(host)
end
before do
diff --git a/spec/unit/node/environment_spec.rb b/spec/unit/node/environment_spec.rb
index 7b2d73b8a..be8ae1a94 100755
--- a/spec/unit/node/environment_spec.rb
+++ b/spec/unit/node/environment_spec.rb
@@ -20,111 +20,97 @@ describe Puppet::Node::Environment do
it "should use the filetimeout for the ttl for the modulepath" do
Puppet::Node::Environment.attr_ttl(:modulepath).should == Integer(Puppet[:filetimeout])
end
-
+
it "should use the filetimeout for the ttl for the module list" do
Puppet::Node::Environment.attr_ttl(:modules).should == Integer(Puppet[:filetimeout])
end
-
+
it "should use the default environment if no name is provided while initializing an environment" do
Puppet[:environment] = "one"
Puppet::Node::Environment.new.name.should == :one
end
-
+
it "should treat environment instances as singletons" do
Puppet::Node::Environment.new("one").should equal(Puppet::Node::Environment.new("one"))
end
-
+
it "should treat an environment specified as names or strings as equivalent" do
Puppet::Node::Environment.new(:one).should equal(Puppet::Node::Environment.new("one"))
end
-
+
it "should return its name when converted to a string" do
Puppet::Node::Environment.new(:one).to_s.should == "one"
end
-
+
it "should just return any provided environment if an environment is provided as the name" do
one = Puppet::Node::Environment.new(:one)
Puppet::Node::Environment.new(one).should equal(one)
end
-
+
describe "when managing known resource types" do
before do
@collection = Puppet::Resource::TypeCollection.new(env)
env.stubs(:perform_initial_import).returns(Puppet::Parser::AST::Hostclass.new(''))
- Thread.current[:known_resource_types] = nil
+ $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)
end
-
+
it "should reuse any existing resource type collection" do
env.known_resource_types.should equal(env.known_resource_types)
end
-
+
it "should perform the initial import when creating a new collection" do
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.should equal(@collection)
end
-
+
it "should return the current thread associated collection if there is one" do
- Thread.current[:known_resource_types] = @collection
-
+ $known_resource_types = @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.expects(:require_reparse?).returns(false)
- Puppet::Resource::TypeCollection.stubs(:new).with(env).returns @collection
-
- t = Thread.new {
- 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.stubs(:require_reparse?).returns true
- Thread.current[:known_resource_types] = nil
+ $known_resource_types = nil
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)
end
end
-
+
it "should validate the modulepath directories" do
real_file = tmpdir('moduledir')
path = %W[/one /two #{real_file}].join(File::PATH_SEPARATOR)
-
+
Puppet[:modulepath] = path
-
+
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.withenv("PUPPETLIB" => %w{/l1 /l2}.join(File::PATH_SEPARATOR)) do
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
-
+
env.modulepath.should == %w{/l1 /l2 /one /two}
end
end
-
+
describe "when validating modulepath or manifestdir directories" do
before :each do
@path_one = tmpdir("path_one")
@@ -132,69 +118,69 @@ describe Puppet::Node::Environment do
sep = File::PATH_SEPARATOR
Puppet[:modulepath] = "#{@path_one}#{sep}#{@path_two}"
end
-
+
it "should not return non-directories" do
FileTest.expects(:directory?).with(@path_one).returns true
FileTest.expects(:directory?).with(@path_two).returns false
-
+
env.validate_dirs([@path_one, @path_two]).should == [@path_one]
end
-
+
it "should use the current working directory to fully-qualify unqualified paths" do
FileTest.stubs(:directory?).returns true
-
two = File.expand_path("two")
+
env.validate_dirs([@path_one, 'two']).should == [@path_one, two]
end
end
-
+
describe "when modeling a specific environment" do
it "should have a method for returning the environment name" do
Puppet::Node::Environment.new("testing").name.should == :testing
end
-
+
it "should provide an array-like accessor method for returning any environment-specific setting" do
env.should respond_to(:[])
end
-
+
it "should ask the Puppet settings instance for the setting qualified with the environment name" do
Puppet.settings.set_value(:server, "myval", :testing)
env[:server].should == "myval"
end
-
+
it "should be able to return an individual module that exists in its module path" do
env.stubs(:modules).returns [Puppet::Module.new('one', "/one", mock("env"))]
-
+
mod = env.module('one')
mod.should be_a(Puppet::Module)
mod.name.should == 'one'
end
-
+
it "should not return a module if the module doesn't exist" do
env.stubs(:modules).returns [Puppet::Module.new('one', "/one", mock("env"))]
-
+
env.module('two').should be_nil
end
-
+
it "should return nil if asked for a module that does not exist in its path" do
modpath = tmpdir('modpath')
env.modulepath = [modpath]
-
+
env.module("one").should be_nil
end
-
+
describe "module data" 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
-
+
describe "#modules_by_path" do
it "should return an empty list if there are no modules" do
env.modules_by_path.should == {
@@ -202,19 +188,19 @@ describe Puppet::Node::Environment do
@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', modpath1, env)],
@second => [Puppet::Module.new('foo', modpath2, env)]
}
end
-
+
it "should ignore modules with invalid names" do
FileUtils.mkdir_p(File.join(@first, 'foo'))
FileUtils.mkdir_p(File.join(@first, 'foo2'))
@@ -226,12 +212,12 @@ describe Puppet::Node::Environment do
FileUtils.mkdir_p(File.join(@first, '-foo'))
FileUtils.mkdir_p(File.join(@first, 'foo-'))
FileUtils.mkdir_p(File.join(@first, 'foo--bar'))
-
+
env.modules_by_path[@first].collect{|mod| mod.name}.sort.should == %w{foo foo-bar foo2 foo_bar}
end
-
+
end
-
+
describe "#module_requirements" do
it "should return a list of what modules depend on other modules" do
PuppetSpec::Modules.create(
@@ -266,7 +252,7 @@ describe Puppet::Node::Environment do
:dependencies => [{ 'name' => 'puppetlabs/bar', "version_requirement" => "~3.0.0" }]
}
)
-
+
env.module_requirements.should == {
'puppetlabs/alpha' => [],
'puppetlabs/foo' => [
@@ -297,7 +283,7 @@ describe Puppet::Node::Environment do
}
end
end
-
+
describe ".module_by_forge_name" do
it "should find modules by forge_name" do
mod = PuppetSpec::Modules.create(
@@ -308,7 +294,7 @@ describe Puppet::Node::Environment do
)
env.module_by_forge_name('puppetlabs/baz').should == mod
end
-
+
it "should not find modules with same name by the wrong author" do
mod = PuppetSpec::Modules.create(
'baz',
@@ -318,17 +304,17 @@ describe Puppet::Node::Environment do
)
env.module_by_forge_name('puppetlabs/baz').should == nil
end
-
+
it "should return nil when the module can't be found" do
env.module_by_forge_name('ima/nothere').should be_nil
end
end
-
+
describe ".modules" do
it "should return an empty list if there are no modules" do
env.modules.should == []
end
-
+
it "should return a module named for every directory in each module path" do
%w{foo bar}.each do |mod_name|
FileUtils.mkdir_p(File.join(@first, mod_name))
@@ -338,14 +324,14 @@ describe Puppet::Node::Environment do
end
env.modules.collect{|mod| mod.name}.sort.should == %w{foo bar bee baz}.sort
end
-
+
it "should remove duplicates" do
FileUtils.mkdir_p(File.join(@first, 'foo'))
FileUtils.mkdir_p(File.join(@second, 'foo'))
-
+
env.modules.collect{|mod| mod.name}.sort.should == %w{foo}
end
-
+
it "should ignore modules with invalid names" do
FileUtils.mkdir_p(File.join(@first, 'foo'))
FileUtils.mkdir_p(File.join(@first, 'foo2'))
@@ -353,63 +339,63 @@ describe Puppet::Node::Environment do
FileUtils.mkdir_p(File.join(@first, 'foo_bar'))
FileUtils.mkdir_p(File.join(@first, 'foo=bar'))
FileUtils.mkdir_p(File.join(@first, 'foo bar'))
-
+
env.modules.collect{|mod| mod.name}.sort.should == %w{foo foo-bar foo2 foo_bar}
end
-
+
it "should create modules with the correct environment" do
FileUtils.mkdir_p(File.join(@first, 'foo'))
env.modules.each {|mod| mod.environment.should == env }
end
-
+
end
end
-
+
it "should cache the module list" do
env.modulepath = %w{/a}
Dir.expects(:entries).once.with("/a").returns %w{foo}
-
+
env.modules
env.modules
end
end
-
+
describe Puppet::Node::Environment::Helper do
before do
@helper = Object.new
@helper.extend(Puppet::Node::Environment::Helper)
end
-
+
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
@helper.environment = Puppet::Node::Environment.new(:foo)
@helper.environment.name.should == :foo
end
-
+
it "should accept an environment as a string" do
@helper.environment = 'foo'
@helper.environment.name.should == :foo
end
end
-
+
describe "when performing initial import" do
before do
@parser = Puppet::Parser::ParserFactory.parser("test")
# @parser = Puppet::Parser::EParserAdapter.new(Puppet::Parser::Parser.new("test")) # TODO: FIX PARSER FACTORY
Puppet::Parser::ParserFactory.stubs(:parser).returns @parser
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 }
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
filename = tmpfile('myfile')
File.open(filename, 'w'){|f| }
@@ -418,7 +404,7 @@ describe Puppet::Node::Environment do
@parser.expects(:parse)
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
filename = tmpfile('myfile')
Puppet.settings[:code] = ""
@@ -427,15 +413,15 @@ describe Puppet::Node::Environment do
@parser.expects(:parse).once
env.instance_eval { perform_initial_import }
end
-
+
it "should fail helpfully if there is an error importing" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
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)
end
-
+
it "should not do anything if the ignore_import settings is set" do
Puppet.settings[:ignoreimport] = true
@parser.expects(:string=).never
@@ -443,11 +429,11 @@ describe Puppet::Node::Environment do
@parser.expects(:parse).never
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)
-
+
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
@@ -465,5 +451,5 @@ describe Puppet::Node::Environment do
end
it_behaves_like 'the environment'
end
-
+
end
diff --git a/spec/unit/node/facts_spec.rb b/spec/unit/node/facts_spec.rb
index 9ba6baa11..55e3dbbf6 100755
--- a/spec/unit/node/facts_spec.rb
+++ b/spec/unit/node/facts_spec.rb
@@ -1,8 +1,17 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'matchers/json'
require 'puppet/node/facts'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ describe "catalog facts schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, FACTS_SCHEMA)
+ end
+ end
+
+end
+
describe Puppet::Node::Facts, "when indirecting" do
before do
@facts = Puppet::Node::Facts.new("me")
@@ -143,8 +152,16 @@ describe Puppet::Node::Facts, "when indirecting" do
result = PSON.parse(facts.to_pson)
result['name'].should == facts.name
result['values'].should == facts.values.reject { |key, value| key.to_s =~ /_/ }
- result['timestamp'].should == facts.timestamp.to_s
- result['expiration'].should == facts.expiration.to_s
+ result['timestamp'].should == facts.timestamp.iso8601(9)
+ result['expiration'].should == facts.expiration.iso8601(9)
+ end
+
+ it "should generate valid facts data against the facts schema", :unless => Puppet.features.microsoft_windows? do
+ Time.stubs(:now).returns(@timestamp)
+ facts = Puppet::Node::Facts.new("foo", {'a' => 1, 'b' => 2, 'c' => 3})
+ facts.expiration = @expiration
+
+ JSON::Validator.validate!(FACTS_SCHEMA, facts.to_pson)
end
it "should not include nil values" do
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 5c36149ad..f8691ed9d 100755
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -2,6 +2,17 @@
require 'spec_helper'
require 'matchers/json'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ NODE_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__), '../../api/schemas/node.json')))
+
+ describe "node schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, NODE_SCHEMA)
+ end
+ end
+end
+
describe Puppet::Node do
it "should register its document type as Node" do
PSON.registered_document_types["Node"].should equal(Puppet::Node)
@@ -55,6 +66,38 @@ describe Puppet::Node do
new_node.name.should == node.name
end
+ it "can round-trip through pson" do
+ facts = Puppet::Node::Facts.new("hello", "one" => "c", "two" => "b")
+ node = Puppet::Node.new("hello",
+ :environment => 'kjhgrg',
+ :classes => ['erth', 'aiu'],
+ :parameters => {"hostname"=>"food"}
+ )
+ new_node = Puppet::Node.convert_from('pson', node.render('pson'))
+ new_node.environment.should == node.environment
+ new_node.parameters.should == node.parameters
+ new_node.classes.should == node.classes
+ new_node.name.should == node.name
+ end
+
+ it "validates against the node json schema", :unless => Puppet.features.microsoft_windows? do
+ facts = Puppet::Node::Facts.new("hello", "one" => "c", "two" => "b")
+ node = Puppet::Node.new("hello",
+ :environment => 'kjhgrg',
+ :classes => ['erth', 'aiu'],
+ :parameters => {"hostname"=>"food"}
+ )
+ JSON::Validator.validate!(NODE_SCHEMA, node.to_pson)
+ end
+
+ it "when missing optional parameters validates against the node json schema", :unless => Puppet.features.microsoft_windows? do
+ facts = Puppet::Node::Facts.new("hello", "one" => "c", "two" => "b")
+ node = Puppet::Node.new("hello",
+ :environment => 'kjhgrg'
+ )
+ JSON::Validator.validate!(NODE_SCHEMA, node.to_pson)
+ end
+
describe "when converting to json" do
before do
@node = Puppet::Node.new("mynode")
diff --git a/spec/unit/parameter/boolean_spec.rb b/spec/unit/parameter/boolean_spec.rb
index 7039c42fc..505bc561f 100644
--- a/spec/unit/parameter/boolean_spec.rb
+++ b/spec/unit/parameter/boolean_spec.rb
@@ -5,21 +5,31 @@ require 'puppet/parameter/boolean'
describe Puppet::Parameter::Boolean do
let (:resource) { mock('resource') }
- subject { described_class.new(:resource => resource) }
-
- [ true, :true, 'true', :yes, 'yes', 'TrUe', 'yEs' ].each do |arg|
- it "should munge #{arg.inspect} as true" do
- subject.munge(arg).should == true
+ describe "after initvars" do
+ before { described_class.initvars }
+ it "should have the correct value_collection" do
+ described_class.value_collection.values.sort.should ==
+ [:true, :false, :yes, :no].sort
end
end
- [ false, :false, 'false', :no, 'no', 'FaLSE', 'nO' ].each do |arg|
- it "should munge #{arg.inspect} as false" do
- subject.munge(arg).should == false
+
+ describe "instances" do
+ subject { described_class.new(:resource => resource) }
+
+ [ true, :true, 'true', :yes, 'yes', 'TrUe', 'yEs' ].each do |arg|
+ it "should munge #{arg.inspect} as true" do
+ subject.munge(arg).should == true
+ end
end
- end
- [ nil, :undef, 'undef', '0', 0, '1', 1, 9284 ].each do |arg|
- it "should fail to munge #{arg.inspect}" do
- expect { subject.munge(arg) }.to raise_error Puppet::Error
+ [ false, :false, 'false', :no, 'no', 'FaLSE', 'nO' ].each do |arg|
+ it "should munge #{arg.inspect} as false" do
+ subject.munge(arg).should == false
+ end
+ end
+ [ nil, :undef, 'undef', '0', 0, '1', 1, 9284 ].each do |arg|
+ it "should fail to munge #{arg.inspect}" do
+ expect { subject.munge(arg) }.to raise_error Puppet::Error
+ end
end
end
end
diff --git a/spec/unit/parser/ast/resourceparam_spec.rb b/spec/unit/parser/ast/resourceparam_spec.rb
new file mode 100644
index 000000000..818f146d3
--- /dev/null
+++ b/spec/unit/parser/ast/resourceparam_spec.rb
@@ -0,0 +1,51 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+
+describe Puppet::Parser::AST::ResourceParam do
+
+ ast = Puppet::Parser::AST
+
+ before :each do
+ @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("mynode"))
+ @scope = Puppet::Parser::Scope.new(@compiler)
+ @params = ast::ASTArray.new({})
+ @compiler.stubs(:add_override)
+ end
+
+ it "should evaluate the parameter value" do
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns('value')
+ ast::ResourceParam.new(:param => 'myparam', :value => object).evaluate(@scope)
+ end
+
+ it "should return a Puppet::Parser::Resource::Param on evaluation" do
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns('value')
+ evaled = ast::ResourceParam.new(:param => 'myparam', :value => object).evaluate(@scope)
+ evaled.should be_a(Puppet::Parser::Resource::Param)
+ evaled.name.to_s.should == 'myparam'
+ evaled.value.to_s.should == 'value'
+ end
+
+ it "should copy line numbers to Puppet::Parser::Resource::Param" do
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns('value')
+ evaled = ast::ResourceParam.new(:param => 'myparam', :value => object, :line => 42).evaluate(@scope)
+ evaled.line.should == 42
+ end
+
+ it "should copy source file to Puppet::Parser::Resource::Param" do
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns('value')
+ evaled = ast::ResourceParam.new(:param => 'myparam', :value => object, :file => 'foo.pp').evaluate(@scope)
+ evaled.file.should == 'foo.pp'
+ end
+
+ it "should change nil parameter values to undef" do
+ object = mock 'object'
+ object.expects(:safeevaluate).with(@scope).returns(nil)
+ evaled = ast::ResourceParam.new(:param => 'myparam', :value => object).evaluate(@scope)
+ evaled.should be_a(Puppet::Parser::Resource::Param)
+ evaled.value.should == :undef
+ end
+end
diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb
index 8e71756e1..68210a4df 100755
--- a/spec/unit/parser/compiler_spec.rb
+++ b/spec/unit/parser/compiler_spec.rb
@@ -1,5 +1,6 @@
#! /usr/bin/env ruby
require 'spec_helper'
+require 'puppet_spec/compiler'
class CompilerTestResource
attr_accessor :builtin, :virtual, :evaluated, :type, :title
@@ -106,22 +107,20 @@ describe Puppet::Parser::Compiler do
@compiler.classlist.sort.should == %w{one two}.sort
end
- it "should clear the thread local caches before compile" do
+ it "should clear the global caches before compile" do
compiler = stub 'compiler'
Puppet::Parser::Compiler.expects(:new).with(@node).returns compiler
catalog = stub 'catalog'
compiler.expects(:compile).returns catalog
catalog.expects(:to_resource)
- [:known_resource_types, :env_module_directories].each do |var|
- Thread.current[var] = "rspec"
- end
+ $known_resource_types = "rspec"
+ $env_module_directories = "rspec"
Puppet::Parser::Compiler.compile(@node)
- [:known_resource_types, :env_module_directories].each do |var|
- Thread.current[var].should == nil
- end
+ $known_resource_types = nil
+ $env_module_directories = nil
end
describe "when initializing" do
@@ -218,27 +217,6 @@ describe Puppet::Parser::Compiler do
@compiler.catalog.server_version.should == "3"
end
- it "should evaluate any existing classes named in the node" do
- classes = %w{one two three four}
- main = stub 'main'
- one = stub 'one', :name => "one"
- three = stub 'three', :name => "three"
- @node.stubs(:name).returns("whatever")
- @node.stubs(:classes).returns(classes)
- compile_stub(:evaluate_node_classes)
-
- @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope)
- @compiler.compile
- end
-
- it "should evaluate any parameterized classes named in the node" do
- classes = {'foo'=>{'p1'=>'one'}, 'bar'=>{'p2'=>'two'}}
- @node.stubs(:classes).returns(classes)
- @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope)
- @compiler.compile
- end
-
-
it "should evaluate the main class if it exists" do
compile_stub(:evaluate_main)
main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "")
@@ -262,12 +240,6 @@ describe Puppet::Parser::Compiler do
@compiler.catalog.edge?(stage, klass).should be_true
end
- it "should evaluate any node classes" do
- @node.stubs(:classes).returns(%w{one two three four})
- @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope)
- @compiler.send(:evaluate_node_classes)
- end
-
it "should evaluate all added collections" do
colls = []
# And when the collections fail to evaluate.
@@ -655,7 +627,7 @@ describe Puppet::Parser::Compiler do
catalog = @compiler.compile
r2 = catalog.resources.detect {|r| r.title == 'Bar::Foo' }
- r2.tags.should =~ ['bar::foo', 'class', 'bar', 'foo']
+ r2.tags.should == Puppet::Util::TagSet.new(['bar::foo', 'class', 'bar', 'foo'])
end
end
@@ -791,6 +763,102 @@ describe Puppet::Parser::Compiler do
end
end
+ describe "when evaluating node classes" do
+ include PuppetSpec::Compiler
+
+ describe "when provided classes in array format" do
+ let(:node) { Puppet::Node.new('someone', :classes => ['something']) }
+
+ describe "when the class exists" do
+ it "should succeed if the class is already included" do
+ manifest = <<-MANIFEST
+ class something {}
+ include something
+ MANIFEST
+
+ catalog = compile_to_catalog(manifest, node)
+
+ catalog.resource('Class', 'Something').should_not be_nil
+ end
+
+ it "should evaluate the class without parameters if it's not already included" do
+ manifest = "class something {}"
+
+ catalog = compile_to_catalog(manifest, node)
+
+ catalog.resource('Class', 'Something').should_not be_nil
+ end
+ end
+
+ it "should fail if the class doesn't exist" do
+ expect { compile_to_catalog('', node) }.to raise_error(Puppet::Error, /Could not find class something/)
+ end
+ end
+
+ describe "when provided classes in hash format" do
+ describe "for classes without parameters" do
+ let(:node) { Puppet::Node.new('someone', :classes => {'something' => {}}) }
+
+ describe "when the class exists" do
+ it "should succeed if the class is already included" do
+ manifest = <<-MANIFEST
+ class something {}
+ include something
+ MANIFEST
+
+ catalog = compile_to_catalog(manifest, node)
+
+ catalog.resource('Class', 'Something').should_not be_nil
+ end
+
+ it "should evaluate the class if it's not already included" do
+ manifest = <<-MANIFEST
+ class something {}
+ MANIFEST
+
+ catalog = compile_to_catalog(manifest, node)
+
+ catalog.resource('Class', 'Something').should_not be_nil
+ end
+ end
+
+ it "should fail if the class doesn't exist" do
+ expect { compile_to_catalog('', node) }.to raise_error(Puppet::Error, /Could not find class something/)
+ end
+ end
+
+ describe "for classes with parameters" do
+ let(:node) { Puppet::Node.new('someone', :classes => {'something' => {'configuron' => 'defrabulated'}}) }
+
+ describe "when the class exists" do
+ it "should fail if the class is already included" do
+ manifest = <<-MANIFEST
+ class something($configuron=frabulated) {}
+ include something
+ MANIFEST
+
+ expect { compile_to_catalog(manifest, node) }.to raise_error(Puppet::Error, /Class\[Something\] is already declared/)
+ end
+
+ it "should evaluate the class if it's not already included" do
+ manifest = <<-MANIFEST
+ class something($configuron=frabulated) {}
+ MANIFEST
+
+ catalog = compile_to_catalog(manifest, node)
+
+ resource = catalog.resource('Class', 'Something')
+ resource['configuron'].should == 'defrabulated'
+ end
+ end
+
+ it "should fail if the class doesn't exist" do
+ expect { compile_to_catalog('', node) }.to raise_error(Puppet::Error, /Could not find class something/)
+ end
+ end
+ end
+ end
+
describe "when managing resource overrides" do
before do
diff --git a/spec/unit/parser/eparser_adapter_spec.rb b/spec/unit/parser/eparser_adapter_spec.rb
index 051633434..173cfb783 100644
--- a/spec/unit/parser/eparser_adapter_spec.rb
+++ b/spec/unit/parser/eparser_adapter_spec.rb
@@ -365,42 +365,42 @@ describe Puppet::Parser do
end
context "when parsing method calls" do
it "should parse method call with one param lambda" do
- expect { @parser.parse("$a.foreach {|$a| debug $a }") }.to_not raise_error
+ expect { @parser.parse("$a.each |$a|{ debug $a }") }.to_not raise_error
end
it "should parse method call with two param lambda" do
- expect { @parser.parse("$a.foreach {|$a,$b| debug $a }") }.to_not raise_error
+ expect { @parser.parse("$a.each |$a,$b|{ debug $a }") }.to_not raise_error
end
it "should parse method call with two param lambda and default value" do
- expect { @parser.parse("$a.foreach {|$a,$b=1| debug $a }") }.to_not raise_error
+ expect { @parser.parse("$a.each |$a,$b=1|{ debug $a }") }.to_not raise_error
end
it "should parse method call without lambda (statement)" do
- expect { @parser.parse("$a.foreach") }.to_not raise_error
+ expect { @parser.parse("$a.each") }.to_not raise_error
end
it "should parse method call without lambda (expression)" do
- expect { @parser.parse("$x = $a.foreach + 1") }.to_not raise_error
+ expect { @parser.parse("$x = $a.each + 1") }.to_not raise_error
end
context "a receiver expression of type" do
it "variable should be allowed" do
- expect { @parser.parse("$a.foreach") }.to_not raise_error
+ expect { @parser.parse("$a.each") }.to_not raise_error
end
it "hasharrayaccess should be allowed" do
- expect { @parser.parse("$a[0][1].foreach") }.to_not raise_error
+ expect { @parser.parse("$a[0][1].each") }.to_not raise_error
end
it "quoted text should be allowed" do
- expect { @parser.parse("\"monkey\".foreach") }.to_not raise_error
- expect { @parser.parse("'monkey'.foreach") }.to_not raise_error
+ expect { @parser.parse("\"monkey\".each") }.to_not raise_error
+ expect { @parser.parse("'monkey'.each") }.to_not raise_error
end
it "selector text should be allowed" do
- expect { @parser.parse("$a ? { 'banana'=>[1,2,3]}.foreach") }.to_not raise_error
+ expect { @parser.parse("$a ? { 'banana'=>[1,2,3]}.each") }.to_not raise_error
end
it "function call should be allowed" do
- expect { @parser.parse("duh(1,2,3).foreach") }.to_not raise_error
+ expect { @parser.parse("duh(1,2,3).each") }.to_not raise_error
end
it "method call should be allowed" do
expect { @parser.parse("$a.foo.bar") }.to_not raise_error
end
it "chained method calls with lambda should be allowed" do
- expect { @parser.parse("$a.foo{||}.bar{||}") }.to_not raise_error
+ expect { @parser.parse("$a.foo||{}.bar||{}") }.to_not raise_error
end
end
end
diff --git a/spec/unit/parser/files_spec.rb b/spec/unit/parser/files_spec.rb
index 2e84216cb..ca7e45b13 100755
--- a/spec/unit/parser/files_spec.rb
+++ b/spec/unit/parser/files_spec.rb
@@ -28,7 +28,7 @@ describe Puppet::Parser::Files do
Puppet[:templatedir] = "/my/templates"
Puppet[:modulepath] = "/one:/two"
File.stubs(:directory?).returns(true)
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet::Parser::Files.find_template("mymod/mytemplate").should == File.join(Puppet[:templatedir], "mymod/mytemplate")
end
@@ -43,59 +43,59 @@ describe Puppet::Parser::Files do
end
it "should return unqualified templates if they exist in the template dir" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::Parser::Files.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Parser::Files.find_template("mytemplate").should == "/my/templates/mytemplate"
end
it "should only return templates if they actually exist" do
- FileTest.expects(:exist?).with("/my/templates/mytemplate").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/my/templates/mytemplate").returns true
Puppet::Parser::Files.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Parser::Files.find_template("mytemplate").should == "/my/templates/mytemplate"
end
it "should return nil when asked for a template that doesn't exist" do
- FileTest.expects(:exist?).with("/my/templates/mytemplate").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("/my/templates/mytemplate").returns false
Puppet::Parser::Files.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Parser::Files.find_template("mytemplate").should be_nil
end
it "should search in the template directories before modules" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::Parser::Files.stubs(:templatepath).with(nil).returns(["/my/templates"])
Puppet::Module.expects(:find).never
Puppet::Parser::Files.find_template("mytemplate")
end
it "should accept relative templatedirs" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet[:templatedir] = "my/templates"
File.expects(:directory?).with(File.expand_path("my/templates")).returns(true)
Puppet::Parser::Files.find_template("mytemplate").should == File.expand_path("my/templates/mytemplate")
end
it "should use the environment templatedir if no module is found and an environment is specified" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::Parser::Files.stubs(:templatepath).with("myenv").returns(["/myenv/templates"])
Puppet::Parser::Files.find_template("mymod/mytemplate", "myenv").should == "/myenv/templates/mymod/mytemplate"
end
it "should use first dir from environment templatedir if no module is found and an environment is specified" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Puppet::Parser::Files.stubs(:templatepath).with("myenv").returns(["/myenv/templates", "/two/templates"])
Puppet::Parser::Files.find_template("mymod/mytemplate", "myenv").should == "/myenv/templates/mymod/mytemplate"
end
it "should use a valid dir when templatedir is a path for unqualified templates and the first dir contains template" do
Puppet::Parser::Files.stubs(:templatepath).returns(["/one/templates", "/two/templates"])
- FileTest.expects(:exist?).with("/one/templates/mytemplate").returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with("/one/templates/mytemplate").returns(true)
Puppet::Parser::Files.find_template("mytemplate").should == "/one/templates/mytemplate"
end
it "should use a valid dir when templatedir is a path for unqualified templates and only second dir contains template" do
Puppet::Parser::Files.stubs(:templatepath).returns(["/one/templates", "/two/templates"])
- FileTest.expects(:exist?).with("/one/templates/mytemplate").returns(false)
- FileTest.expects(:exist?).with("/two/templates/mytemplate").returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with("/one/templates/mytemplate").returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with("/two/templates/mytemplate").returns(true)
Puppet::Parser::Files.find_template("mytemplate").should == "/two/templates/mytemplate"
end
diff --git a/spec/unit/parser/functions/contain_spec.rb b/spec/unit/parser/functions/contain_spec.rb
new file mode 100644
index 000000000..3150e0c8e
--- /dev/null
+++ b/spec/unit/parser/functions/contain_spec.rb
@@ -0,0 +1,185 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+require 'puppet_spec/compiler'
+require 'puppet/parser/functions'
+require 'matchers/containment_matchers'
+require 'matchers/include_in_order'
+
+describe 'The "contain" function' do
+ include PuppetSpec::Compiler
+ include ContainmentMatchers
+
+ it "includes the class" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ include container
+ MANIFEST
+
+ expect(catalog.classes).to include("contained")
+ end
+
+ it "makes the class contained in the current class" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ include container
+ MANIFEST
+
+ expect(catalog).to contain_class("contained").in("container")
+ end
+
+ it "can contain multiple classes" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class a {
+ notify { "a": }
+ }
+
+ class b {
+ notify { "b": }
+ }
+
+ class container {
+ contain a, b
+ }
+
+ include container
+ MANIFEST
+
+ expect(catalog).to contain_class("a").in("container")
+ expect(catalog).to contain_class("b").in("container")
+ end
+
+ context "when containing a class in multiple classes" do
+ it "creates a catalog with all containment edges" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ class another {
+ contain contained
+ }
+
+ include container
+ include another
+ MANIFEST
+
+ expect(catalog).to contain_class("contained").in("container")
+ expect(catalog).to contain_class("contained").in("another")
+ end
+
+ it "and there are no dependencies applies successfully" do
+ manifest = <<-MANIFEST
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ class another {
+ contain contained
+ }
+
+ include container
+ include another
+ MANIFEST
+
+ expect { apply_compiled_manifest(manifest) }.not_to raise_error
+ end
+
+ it "and there are explicit dependencies on the containing class causes a dependency cycle" do
+ manifest = <<-MANIFEST
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ class another {
+ contain contained
+ }
+
+ include container
+ include another
+
+ Class["container"] -> Class["another"]
+ MANIFEST
+
+ expect { apply_compiled_manifest(manifest) }.to raise_error(
+ Puppet::Error,
+ /Found 1 dependency cycle/
+ )
+ end
+ end
+
+ it "does not create duplicate edges" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ contain contained
+ }
+
+ include container
+ MANIFEST
+
+ contained = catalog.resource("Class", "contained")
+ container = catalog.resource("Class", "container")
+
+ expect(catalog.edges_between(container, contained)).to have(1).item
+ end
+
+ context "when a containing class has a dependency order" do
+ it "the contained class is applied in that order" do
+ catalog = compile_to_relationship_graph(<<-MANIFEST)
+ class contained {
+ notify { "contained": }
+ }
+
+ class container {
+ contain contained
+ }
+
+ class first {
+ notify { "first": }
+ }
+
+ class last {
+ notify { "last": }
+ }
+
+ include container, first, last
+
+ Class["first"] -> Class["container"] -> Class["last"]
+ MANIFEST
+
+ expect(order_resources_traversed_in(catalog)).to include_in_order(
+ "Notify[first]", "Notify[contained]", "Notify[last]"
+ )
+ end
+ end
+end
diff --git a/spec/unit/parser/functions/create_resources_spec.rb b/spec/unit/parser/functions/create_resources_spec.rb
index a0c3253ab..79ed02f22 100755
--- a/spec/unit/parser/functions/create_resources_spec.rb
+++ b/spec/unit/parser/functions/create_resources_spec.rb
@@ -23,6 +23,14 @@ describe 'function for dynamically creating resources' do
expect { @scope.function_create_resources(['foo', 'bar', 'blah', 'baz']) }.to raise_error(ArgumentError, 'create_resources(): wrong number of arguments (4; must be 2 or 3)')
end
+ it 'should require second argument to be a hash' do
+ expect { @scope.function_create_resources(['foo','bar']) }.to raise_error(ArgumentError, 'create_resources(): second argument must be a hash')
+ end
+
+ it 'should require optional third argument to be a hash' do
+ expect { @scope.function_create_resources(['foo',{},'foo']) }.to raise_error(ArgumentError, 'create_resources(): third argument, if provided, must be a hash')
+ end
+
describe 'when creating native types' do
it 'empty hash should not cause resources to be added' do
noop_catalog = compile_to_catalog("create_resources('file', {})")
@@ -75,12 +83,12 @@ describe 'function for dynamically creating resources' do
end
describe 'when dynamically creating resource types' do
- it 'should be able to create defined resoure types' do
+ it 'should be able to create defined resource types' do
catalog = compile_to_catalog(<<-MANIFEST)
define foocreateresource($one) {
notify { $name: message => $one }
}
-
+
create_resources('foocreateresource', {'blah'=>{'one'=>'two'}})
MANIFEST
catalog.resource(:notify, "blah")['message'].should == 'two'
@@ -92,7 +100,7 @@ describe 'function for dynamically creating resources' do
define foocreateresource($one) {
notify { $name: message => $one }
}
-
+
create_resources('foocreateresource', {'blah'=>{}})
MANIFEST
}.to raise_error(Puppet::Error, 'Must pass one to Foocreateresource[blah] on node foonode')
@@ -103,7 +111,7 @@ describe 'function for dynamically creating resources' do
define foocreateresource($one) {
notify { $name: message => $one }
}
-
+
create_resources('foocreateresource', {'blah'=>{'one'=>'two'}, 'blaz'=>{'one'=>'three'}})
MANIFEST
@@ -118,7 +126,7 @@ describe 'function for dynamically creating resources' do
}
notify { test: }
-
+
create_resources('foocreateresource', {'blah'=>{'one'=>'two', 'require' => 'Notify[test]'}})
MANIFEST
diff --git a/spec/unit/parser/functions/generate_spec.rb b/spec/unit/parser/functions/generate_spec.rb
index 90afbc8ea..593703d63 100755
--- a/spec/unit/parser/functions/generate_spec.rb
+++ b/spec/unit/parser/functions/generate_spec.rb
@@ -45,7 +45,7 @@ describe "the generate function" do
scope.function_generate([command]).should == 'yay'
end
- describe "on Windows", :as_platform => :windows do
+ describe "on Windows", :if => Puppet.features.microsoft_windows? do
it "should accept the tilde in the path" do
command = "C:/DOCUME~1/ADMINI~1/foo.bat"
Dir.expects(:chdir).with(File.dirname(command)).returns("yay")
diff --git a/spec/unit/parser/functions_spec.rb b/spec/unit/parser/functions_spec.rb
index 81ff655a3..8ad33c874 100755
--- a/spec/unit/parser/functions_spec.rb
+++ b/spec/unit/parser/functions_spec.rb
@@ -128,7 +128,7 @@ describe Puppet::Parser::Functions do
describe "::get_function" do
it "can retrieve a function defined on the *root* environment" do
- Thread.current[:environment] = nil
+ $environment = nil
function = Puppet::Parser::Functions.newfunction("atest", :type => :rvalue) do
nil
end
@@ -162,7 +162,7 @@ describe Puppet::Parser::Functions do
describe "::merged_functions" do
it "returns functions in both the current and root environment" do
- Thread.current[:environment] = nil
+ $environment = nil
func_a = Puppet::Parser::Functions.newfunction("test_a", :type => :rvalue) do
nil
end
diff --git a/spec/unit/parser/lexer_spec.rb b/spec/unit/parser/lexer_spec.rb
index fc8394cb1..972a8f1bf 100755
--- a/spec/unit/parser/lexer_spec.rb
+++ b/spec/unit/parser/lexer_spec.rb
@@ -861,7 +861,7 @@ describe "when trying to lex a non-existent file" do
it "should return an empty list of tokens" do
lexer = Puppet::Parser::Lexer.new
lexer.file = nofile = tmpfile('lexer')
- File.exists?(nofile).should == false
+ Puppet::FileSystem::File.exist?(nofile).should == false
lexer.fullscan.should == [[false,false]]
end
diff --git a/spec/unit/parser/methods/collect_spec.rb b/spec/unit/parser/methods/collect_spec.rb
deleted file mode 100644
index acc26652a..000000000
--- a/spec/unit/parser/methods/collect_spec.rb
+++ /dev/null
@@ -1,153 +0,0 @@
-require 'puppet'
-require 'spec_helper'
-require 'puppet_spec/compiler'
-
-require 'unit/parser/methods/shared'
-
-describe 'the collect method' do
- include PuppetSpec::Compiler
-
- before :each do
- Puppet[:parser] = "future"
- end
-
- context "using future parser" do
- context "in Ruby style should be callable as" do
- it 'collect on an array (multiplying each value by 2)' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [1,2,3]
- $a.collect {|$x| $x*2}.foreach {|$v|
- file { "/file_$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_4")['ensure'].should == 'present'
- catalog.resource(:file, "/file_6")['ensure'].should == 'present'
- end
-
- it 'collect on a hash selecting keys' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>1,'b'=>2,'c'=>3}
- $a.collect {|$x| $x[0]}.foreach {|$k|
- file { "/file_$k": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_a")['ensure'].should == 'present'
- catalog.resource(:file, "/file_b")['ensure'].should == 'present'
- catalog.resource(:file, "/file_c")['ensure'].should == 'present'
- end
-
- it 'foreach on a hash selecting value' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>1,'b'=>2,'c'=>3}
- $a.collect {|$x| $x[1]}.foreach {|$k|
- file { "/file_$k": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_1")['ensure'].should == 'present'
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
- end
-
- context "handles data type corner cases" do
- it "collect gets values that are false" do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [false,false]
- $a.collect |$x| { $x }.each |$i, $v| {
- file { "/file_$i.$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_0.false")['ensure'].should == 'present'
- catalog.resource(:file, "/file_1.false")['ensure'].should == 'present'
- end
-
- it "collect gets values that are nil" do
- Puppet::Parser::Functions.newfunction(:nil_array, :type => :rvalue) do |args|
- [nil]
- end
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = nil_array()
- $a.collect |$x| { $x }.each |$i, $v| {
- file { "/file_$i.$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_0.")['ensure'].should == 'present'
- end
-
- it "collect gets values that are undef" do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [$does_not_exist]
- $a.collect |$x = "something"| { $x }.each |$i, $v| {
- file { "/file_$i.$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_0.")['ensure'].should == 'present'
- end
- end
-
- context "in Java style should be callable as" do
- shared_examples_for 'java style' do
- it 'collect on an array (multiplying each value by 2)' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [1,2,3]
- $a.collect |$x| #{farr}{ $x*2}.foreach |$v| #{farr}{
- file { "/file_$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_4")['ensure'].should == 'present'
- catalog.resource(:file, "/file_6")['ensure'].should == 'present'
- end
-
- it 'collect on a hash selecting keys' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>1,'b'=>2,'c'=>3}
- $a.collect |$x| #{farr}{ $x[0]}.foreach |$k| #{farr}{
- file { "/file_$k": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_a")['ensure'].should == 'present'
- catalog.resource(:file, "/file_b")['ensure'].should == 'present'
- catalog.resource(:file, "/file_c")['ensure'].should == 'present'
- end
-
- it 'foreach on a hash selecting value' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>1,'b'=>2,'c'=>3}
- $a.collect |$x| #{farr} {$x[1]}.foreach |$k|#{farr}{
- file { "/file_$k": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_1")['ensure'].should == 'present'
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
- end
-
- describe 'without fat arrow' do
- it_should_behave_like 'java style' do
- let(:farr) { '' }
- end
- end
-
- describe 'with fat arrow' do
- it_should_behave_like 'java style' do
- let(:farr) { '=>' }
- end
- end
- end
- end
-
- it_should_behave_like 'all iterative functions argument checks', 'collect'
- it_should_behave_like 'all iterative functions hash handling', 'collect'
-end
diff --git a/spec/unit/parser/methods/each_spec.rb b/spec/unit/parser/methods/each_spec.rb
index 4d276e95d..5e9ce4e0c 100644
--- a/spec/unit/parser/methods/each_spec.rb
+++ b/spec/unit/parser/methods/each_spec.rb
@@ -26,7 +26,7 @@ describe 'the each method' do
it 'each on an array selecting each value - function call style' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1,2,3]
- each ($a) |$index, $v| => {
+ each ($a) |$index, $v| {
file { "/file_$v": ensure => present }
}
MANIFEST
diff --git a/spec/unit/parser/methods/select_spec.rb b/spec/unit/parser/methods/filter_spec.rb
index e61ee3a31..89fb15bbb 100644
--- a/spec/unit/parser/methods/select_spec.rb
+++ b/spec/unit/parser/methods/filter_spec.rb
@@ -4,17 +4,17 @@ require 'puppet_spec/compiler'
require 'unit/parser/methods/shared'
-describe 'the select method' do
+describe 'the filter method' do
include PuppetSpec::Compiler
before :each do
Puppet[:parser] = 'future'
end
- it 'should select on an array (all berries)' do
+ it 'should filter on an array (all berries)' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = ['strawberry','blueberry','orange']
- $a.select {|$x| $x =~ /berry$/}.foreach {|$v|
+ $a.filter |$x|{ $x =~ /berry$/}.each |$v|{
file { "/file_$v": ensure => present }
}
MANIFEST
@@ -26,7 +26,7 @@ describe 'the select method' do
it 'should produce an array when acting on an array' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = ['strawberry','blueberry','orange']
- $b = $a.select {|$x| $x =~ /berry$/}
+ $b = $a.filter |$x|{ $x =~ /berry$/}
file { "/file_${b[0]}": ensure => present }
file { "/file_${b[1]}": ensure => present }
MANIFEST
@@ -35,10 +35,10 @@ describe 'the select method' do
catalog.resource(:file, "/file_blueberry")['ensure'].should == 'present'
end
- it 'selects on a hash (all berries) by key' do
+ it 'filters on a hash (all berries) by key' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
- $a.select {|$x| $x[0] =~ /berry$/}.foreach {|$v|
+ $a.filter |$x|{ $x[0] =~ /berry$/}.each |$v|{
file { "/file_${v[0]}": ensure => present }
}
MANIFEST
@@ -50,7 +50,7 @@ describe 'the select method' do
it 'should produce a hash when acting on a hash' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
- $b = $a.select {|$x| $x[0] =~ /berry$/}
+ $b = $a.filter |$x|{ $x[0] =~ /berry$/}
file { "/file_${b['strawberry']}": ensure => present }
file { "/file_${b['blueberry']}": ensure => present }
file { "/file_${b['orange']}": ensure => present }
@@ -62,10 +62,10 @@ describe 'the select method' do
catalog.resource(:file, "/file_")['ensure'].should == 'present'
end
- it 'selects on a hash (all berries) by value' do
+ it 'filters on a hash (all berries) by value' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {'strawb'=>'red berry','blueb'=>'blue berry','orange'=>'orange fruit'}
- $a.select {|$x| $x[1] =~ /berry$/}.foreach {|$v|
+ $a.filter |$x|{ $x[1] =~ /berry$/}.each |$v|{
file { "/file_${v[0]}": ensure => present }
}
MANIFEST
@@ -74,6 +74,6 @@ describe 'the select method' do
catalog.resource(:file, "/file_blueb")['ensure'].should == 'present'
end
- it_should_behave_like 'all iterative functions argument checks', 'select'
- it_should_behave_like 'all iterative functions hash handling', 'select'
+ it_should_behave_like 'all iterative functions argument checks', 'filter'
+ it_should_behave_like 'all iterative functions hash handling', 'filter'
end
diff --git a/spec/unit/parser/methods/foreach_spec.rb b/spec/unit/parser/methods/foreach_spec.rb
deleted file mode 100755
index 72a9379a4..000000000
--- a/spec/unit/parser/methods/foreach_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-require 'puppet'
-require 'spec_helper'
-require 'puppet_spec/compiler'
-require 'rubygems'
-
-describe 'the foreach method' do
- include PuppetSpec::Compiler
-
- before :each do
- Puppet[:parser] = 'future'
- end
-
- context "should be callable as" do
- it 'foreach on an array selecting each value' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [1,2,3]
- $a.foreach {|$v|
- file { "/file_$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_1")['ensure'].should == 'present'
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
- it 'foreach on an array selecting each value - function call style' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [1,2,3]
- foreach ($a) {|$v|
- file { "/file_$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_1")['ensure'].should == 'present'
- catalog.resource(:file, "/file_2")['ensure'].should == 'present'
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
-
- it 'foreach on an array with index' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [present, absent, present]
- $a.foreach {|$k,$v|
- file { "/file_${$k+1}": ensure => $v }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_1")['ensure'].should == 'present'
- catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
-
- it 'foreach on a hash selecting entries' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>'present','b'=>'absent','c'=>'present'}
- $a.foreach {|$e|
- file { "/file_${e[0]}": ensure => $e[1] }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_a")['ensure'].should == 'present'
- catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
- catalog.resource(:file, "/file_c")['ensure'].should == 'present'
- end
- it 'foreach on a hash selecting key and value' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'a'=>present,'b'=>absent,'c'=>present}
- $a.foreach {|$k, $v|
- file { "/file_$k": ensure => $v }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_a")['ensure'].should == 'present'
- catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
- catalog.resource(:file, "/file_c")['ensure'].should == 'present'
- end
- end
- context "should produce receiver" do
- it 'each checking produced value using single expression' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = [1, 3, 2]
- $b = $a.each |$x| { $x }
- file { "/file_${b[1]}":
- ensure => present
- }
- MANIFEST
-
- catalog.resource(:file, "/file_3")['ensure'].should == 'present'
- end
-
- end
-end
diff --git a/spec/unit/parser/methods/map_spec.rb b/spec/unit/parser/methods/map_spec.rb
new file mode 100644
index 000000000..025501754
--- /dev/null
+++ b/spec/unit/parser/methods/map_spec.rb
@@ -0,0 +1,95 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+
+require 'unit/parser/methods/shared'
+
+describe 'the map method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = "future"
+ end
+
+ context "using future parser" do
+ it 'map on an array (multiplying each value by 2)' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $a.map |$x|{ $x*2}.each |$v|{
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_4")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_6")['ensure'].should == 'present'
+ end
+
+ it 'map on a hash selecting keys' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.map |$x|{ $x[0]}.each |$k|{
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+
+ it 'each on a hash selecting value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.map |$x|{ $x[1]}.each |$k|{
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ context "handles data type corner cases" do
+ it "map gets values that are false" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [false,false]
+ $a.map |$x| { $x }.each |$i, $v| {
+ file { "/file_$i.$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_0.false")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_1.false")['ensure'].should == 'present'
+ end
+
+ it "map gets values that are nil" do
+ Puppet::Parser::Functions.newfunction(:nil_array, :type => :rvalue) do |args|
+ [nil]
+ end
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = nil_array()
+ $a.map |$x| { $x }.each |$i, $v| {
+ file { "/file_$i.$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_0.")['ensure'].should == 'present'
+ end
+
+ it "map gets values that are undef" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [$does_not_exist]
+ $a.map |$x = "something"| { $x }.each |$i, $v| {
+ file { "/file_$i.$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_0.")['ensure'].should == 'present'
+ end
+ end
+ it_should_behave_like 'all iterative functions argument checks', 'map'
+ it_should_behave_like 'all iterative functions hash handling', 'map'
+ end
+end
diff --git a/spec/unit/parser/methods/reduce_spec.rb b/spec/unit/parser/methods/reduce_spec.rb
index 99ecfd18d..5d4549b54 100644
--- a/spec/unit/parser/methods/reduce_spec.rb
+++ b/spec/unit/parser/methods/reduce_spec.rb
@@ -28,40 +28,41 @@ describe 'the reduce method' do
it 'reduce on an array' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1,2,3]
- $b = $a.reduce {|$memo, $x| $memo + $x }
+ $b = $a.reduce |$memo, $x| { $memo + $x }
file { "/file_$b": ensure => present }
MANIFEST
catalog.resource(:file, "/file_6")['ensure'].should == 'present'
- end
+ end
+
it 'reduce on an array with start value' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1,2,3]
- $b = $a.reduce(4) {|$memo, $x| $memo + $x }
+ $b = $a.reduce(4) |$memo, $x| { $memo + $x }
file { "/file_$b": ensure => present }
MANIFEST
-
+
catalog.resource(:file, "/file_10")['ensure'].should == 'present'
- end
+ end
it 'reduce on a hash' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {a=>1, b=>2, c=>3}
$start = [ignored, 4]
- $b = $a.reduce {|$memo, $x| ['sum', $memo[1] + $x[1]] }
+ $b = $a.reduce |$memo, $x| {['sum', $memo[1] + $x[1]] }
file { "/file_${$b[0]}_${$b[1]}": ensure => present }
MANIFEST
-
+
catalog.resource(:file, "/file_sum_6")['ensure'].should == 'present'
- end
+ end
it 'reduce on a hash with start value' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {a=>1, b=>2, c=>3}
$start = ['ignored', 4]
- $b = $a.reduce($start) {|$memo, $x| ['sum', $memo[1] + $x[1]] }
+ $b = $a.reduce($start) |$memo, $x| { ['sum', $memo[1] + $x[1]] }
file { "/file_${$b[0]}_${$b[1]}": ensure => present }
MANIFEST
-
+
catalog.resource(:file, "/file_sum_10")['ensure'].should == 'present'
- end
+ end
end
end
diff --git a/spec/unit/parser/methods/reject_spec.rb b/spec/unit/parser/methods/reject_spec.rb
deleted file mode 100644
index e37eaebc5..000000000
--- a/spec/unit/parser/methods/reject_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'puppet'
-require 'spec_helper'
-require 'puppet_spec/compiler'
-
-require 'unit/parser/methods/shared'
-
-describe 'the reject method' do
- include PuppetSpec::Compiler
-
- before :each do
- Puppet[:parser] = 'future'
- end
-
- it 'rejects on an array (no berries)' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = ['strawberry','blueberry','orange']
- $a.reject {|$x| $x =~ /berry$/}.foreach {|$v|
- file { "/file_$v": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
- catalog.resource(:file, "/file_strawberry").should == nil
- end
-
- it 'produces an array when acting on an array' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = ['strawberry','blueberry','orange']
- $b = $a.reject {|$x| $x =~ /berry$/}
- file { "/file_${b[0]}": ensure => present }
-
- MANIFEST
-
- catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
- catalog.resource(:file, "/file_strawberry").should == nil
- end
-
- it 'rejects on a hash (all berries) by key' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
- $a.reject {|$x| $x[0] =~ /berry$/}.foreach {|$v|
- file { "/file_${v[0]}": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
- end
-
- it 'produces a hash when acting on a hash' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'strawberry'=>'red','blueberry'=>'blue','grape'=>'purple'}
- $b = $a.reject {|$x| $x[0] =~ /berry$/}
- file { "/file_${b[grape]}": ensure => present }
-
- MANIFEST
-
- catalog.resource(:file, "/file_purple")['ensure'].should == 'present'
- end
-
- it 'rejects on a hash (all berries) by value' do
- catalog = compile_to_catalog(<<-MANIFEST)
- $a = {'strawb'=>'red berry','blueb'=>'blue berry','orange'=>'orange fruit'}
- $a.reject {|$x| $x[1] =~ /berry$/}.foreach {|$v|
- file { "/file_${v[0]}": ensure => present }
- }
- MANIFEST
-
- catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
- end
-
- it_should_behave_like 'all iterative functions argument checks', 'reject'
- it_should_behave_like 'all iterative functions hash handling', 'reject'
-end
diff --git a/spec/unit/parser/methods/shared.rb b/spec/unit/parser/methods/shared.rb
index bf9c9f05f..704769d83 100644
--- a/spec/unit/parser/methods/shared.rb
+++ b/spec/unit/parser/methods/shared.rb
@@ -2,7 +2,7 @@
shared_examples_for 'all iterative functions hash handling' do |func|
it 'passes a hash entry as an array of the key and value' do
catalog = compile_to_catalog(<<-MANIFEST)
- {a=>1}.#{func} { |$v| notify { "${v[0]} ${v[1]}": } }
+ {a=>1}.#{func} |$v| { notify { "${v[0]} ${v[1]}": } }
MANIFEST
catalog.resource(:notify, "a 1").should_not be_nil
@@ -14,7 +14,7 @@ shared_examples_for 'all iterative functions argument checks' do |func|
it 'raises an error when defined with more than 1 argument' do
expect do
compile_to_catalog(<<-MANIFEST)
- [1].#{func} { |$x, $yikes| }
+ [1].#{func} |$x, $yikes|{ }
MANIFEST
end.to raise_error(Puppet::Error, /Too few arguments/)
end
@@ -22,7 +22,7 @@ shared_examples_for 'all iterative functions argument checks' do |func|
it 'raises an error when defined with fewer than 1 argument' do
expect do
compile_to_catalog(<<-MANIFEST)
- [1].#{func} { || }
+ [1].#{func} || { }
MANIFEST
end.to raise_error(Puppet::Error, /Too many arguments/)
end
@@ -30,7 +30,7 @@ shared_examples_for 'all iterative functions argument checks' do |func|
it 'raises an error when used against an unsupported type' do
expect do
compile_to_catalog(<<-MANIFEST)
- "not correct".#{func} { |$v| }
+ "not correct".#{func} |$v| { }
MANIFEST
end.to raise_error(Puppet::Error, /must be an Array or a Hash/)
end
@@ -38,7 +38,7 @@ shared_examples_for 'all iterative functions argument checks' do |func|
it 'raises an error when called with any parameters besides a block' do
expect do
compile_to_catalog(<<-MANIFEST)
- [1].#{func}(1) { |$v| }
+ [1].#{func}(1) |$v| { }
MANIFEST
end.to raise_error(Puppet::Error, /Wrong number of arguments/)
end
diff --git a/spec/unit/parser/methods/slice_spec.rb b/spec/unit/parser/methods/slice_spec.rb
index b213415a1..1069bc75a 100644
--- a/spec/unit/parser/methods/slice_spec.rb
+++ b/spec/unit/parser/methods/slice_spec.rb
@@ -27,15 +27,15 @@ describe 'methods' do
end
context "should be callable on array as" do
-
+
it 'slice with explicit parameters' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1, present, 2, absent, 3, present]
- $a.slice(2) |$k,$v| {
+ $a.slice(2) |$k,$v| {
file { "/file_${$k}": ensure => $v }
}
MANIFEST
-
+
catalog.resource(:file, "/file_1")['ensure'].should == 'present'
catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
catalog.resource(:file, "/file_3")['ensure'].should == 'present'
@@ -43,11 +43,11 @@ describe 'methods' do
it 'slice with one parameter' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1, present, 2, absent, 3, present]
- $a.slice(2) |$k| {
+ $a.slice(2) |$k| {
file { "/file_${$k[0]}": ensure => $k[1] }
}
MANIFEST
-
+
catalog.resource(:file, "/file_1")['ensure'].should == 'present'
catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
catalog.resource(:file, "/file_3")['ensure'].should == 'present'
@@ -55,39 +55,39 @@ describe 'methods' do
it 'slice with shorter last slice' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1, present, 2, present, 3, absent]
- $a.slice(4) |$a, $b, $c, $d| {
+ $a.slice(4) |$a, $b, $c, $d| {
file { "/file_$a.$c": ensure => $b }
}
MANIFEST
-
+
catalog.resource(:file, "/file_1.2")['ensure'].should == 'present'
catalog.resource(:file, "/file_3.")['ensure'].should == 'absent'
end
end
context "should be callable on hash as" do
-
+
it 'slice with explicit parameters, missing are empty' do
catalog = compile_to_catalog(<<-MANIFEST)
$a = {1=>present, 2=>present, 3=>absent}
- $a.slice(2) |$a,$b| {
+ $a.slice(2) |$a,$b| {
file { "/file_${a[0]}.${b[0]}": ensure => $a[1] }
}
MANIFEST
-
+
catalog.resource(:file, "/file_1.2")['ensure'].should == 'present'
catalog.resource(:file, "/file_3.")['ensure'].should == 'absent'
end
-
+
end
context "when called without a block" do
it "should produce an array with the result" do
catalog = compile_to_catalog(<<-MANIFEST)
$a = [1, present, 2, absent, 3, present]
- $a.slice(2).each |$k| {
+ $a.slice(2).each |$k| {
file { "/file_${$k[0]}": ensure => $k[1] }
}
MANIFEST
-
+
catalog.resource(:file, "/file_1")['ensure'].should == 'present'
catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
catalog.resource(:file, "/file_3")['ensure'].should == 'present'
diff --git a/spec/unit/parser/parser_spec.rb b/spec/unit/parser/parser_spec.rb
index 38a5c7a85..2c4cf50df 100755
--- a/spec/unit/parser/parser_spec.rb
+++ b/spec/unit/parser/parser_spec.rb
@@ -53,7 +53,7 @@ describe Puppet::Parser do
describe "when parsing files" do
before do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
File.stubs(:read).returns ""
@parser.stubs(:watch_file)
end
diff --git a/spec/unit/parser/resource/param_spec.rb b/spec/unit/parser/resource/param_spec.rb
new file mode 100755
index 000000000..7989d060d
--- /dev/null
+++ b/spec/unit/parser/resource/param_spec.rb
@@ -0,0 +1,44 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+
+describe Puppet::Parser::Resource::Param do
+ it "can be instantiated" do
+ Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo')
+ end
+
+ it "stores the source file" do
+ param = Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo', :file => 'foo.pp')
+ param.file.should == 'foo.pp'
+ end
+
+ it "stores the line number" do
+ param = Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => 'foo', :line => 42)
+ param.line.should == 42
+ end
+
+ context "parameter validation" do
+ it "throws an error when instantiated without a name" do
+ expect {
+ Puppet::Parser::Resource::Param.new(:value => 'foo')
+ }.to raise_error(Puppet::Error, /name is a required option/)
+ end
+
+ it "throws an error when instantiated without a value" do
+ expect {
+ Puppet::Parser::Resource::Param.new(:name => 'myparam')
+ }.to raise_error(Puppet::Error, /value is a required option/)
+ end
+
+ it "throws an error when instantiated with a nil value" do
+ expect {
+ Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => nil)
+ }.to raise_error(Puppet::Error, /value is a required option/)
+ end
+
+ it "includes file/line context in errors" do
+ expect {
+ Puppet::Parser::Resource::Param.new(:name => 'myparam', :value => nil, :file => 'foo.pp', :line => 42)
+ }.to raise_error(Puppet::Error, /foo.pp:42/)
+ end
+ end
+end
diff --git a/spec/unit/parser/resource_spec.rb b/spec/unit/parser/resource_spec.rb
index 221efb83b..74a66d1c1 100755
--- a/spec/unit/parser/resource_spec.rb
+++ b/spec/unit/parser/resource_spec.rb
@@ -90,7 +90,7 @@ describe Puppet::Parser::Resource do
it "should use a Puppet::Resource for converting to a ral resource" do
trans = mock 'resource', :to_ral => "yay"
@resource = mkresource
- @resource.expects(:to_resource).returns trans
+ @resource.expects(:copy_as_resource).returns trans
@resource.to_ral.should == "yay"
end
@@ -124,7 +124,8 @@ describe Puppet::Parser::Resource do
tags = [ "tag1", "tag2" ]
@arguments[:parameters] = [ param(:tag, tags , :source) ]
res = Puppet::Parser::Resource.new("resource", "testing", @arguments)
- (res.tags & tags).should == tags
+ res.should be_tagged("tag1")
+ res.should be_tagged("tag2")
end
end
@@ -445,7 +446,7 @@ describe Puppet::Parser::Resource do
it "should be able to be converted to a normal resource" do
@source = stub 'scope', :name => "myscope"
@resource = mkresource :source => @source
- @resource.should respond_to(:to_resource)
+ @resource.should respond_to(:copy_as_resource)
end
describe "when being converted to a resource" do
@@ -454,19 +455,19 @@ describe Puppet::Parser::Resource do
end
it "should create an instance of Puppet::Resource" do
- @parser_resource.to_resource.should be_instance_of(Puppet::Resource)
+ @parser_resource.copy_as_resource.should be_instance_of(Puppet::Resource)
end
it "should set the type correctly on the Puppet::Resource" do
- @parser_resource.to_resource.type.should == @parser_resource.type
+ @parser_resource.copy_as_resource.type.should == @parser_resource.type
end
it "should set the title correctly on the Puppet::Resource" do
- @parser_resource.to_resource.title.should == @parser_resource.title
+ @parser_resource.copy_as_resource.title.should == @parser_resource.title
end
it "should copy over all of the parameters" do
- result = @parser_resource.to_resource.to_hash
+ result = @parser_resource.copy_as_resource.to_hash
# The name will be in here, also.
result[:foo].should == "bar"
@@ -477,40 +478,40 @@ describe Puppet::Parser::Resource do
@parser_resource.tag "foo"
@parser_resource.tag "bar"
- @parser_resource.to_resource.tags.should == @parser_resource.tags
+ @parser_resource.copy_as_resource.tags.should == @parser_resource.tags
end
it "should copy over the line" do
@parser_resource.line = 40
- @parser_resource.to_resource.line.should == 40
+ @parser_resource.copy_as_resource.line.should == 40
end
it "should copy over the file" do
@parser_resource.file = "/my/file"
- @parser_resource.to_resource.file.should == "/my/file"
+ @parser_resource.copy_as_resource.file.should == "/my/file"
end
it "should copy over the 'exported' value" do
@parser_resource.exported = true
- @parser_resource.to_resource.exported.should be_true
+ @parser_resource.copy_as_resource.exported.should be_true
end
it "should copy over the 'virtual' value" do
@parser_resource.virtual = true
- @parser_resource.to_resource.virtual.should be_true
+ @parser_resource.copy_as_resource.virtual.should be_true
end
it "should convert any parser resource references to Puppet::Resource instances" do
ref = Puppet::Resource.new("file", "/my/file")
@parser_resource = mkresource :source => @source, :parameters => {:foo => "bar", :fee => ref}
- result = @parser_resource.to_resource
+ result = @parser_resource.copy_as_resource
result[:fee].should == Puppet::Resource.new(:file, "/my/file")
end
it "should convert any parser resource references to Puppet::Resource instances even if they are in an array" do
ref = Puppet::Resource.new("file", "/my/file")
@parser_resource = mkresource :source => @source, :parameters => {:foo => "bar", :fee => ["a", ref]}
- result = @parser_resource.to_resource
+ result = @parser_resource.copy_as_resource
result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file")]
end
@@ -518,7 +519,7 @@ describe Puppet::Parser::Resource do
ref1 = Puppet::Resource.new("file", "/my/file1")
ref2 = Puppet::Resource.new("file", "/my/file2")
@parser_resource = mkresource :source => @source, :parameters => {:foo => "bar", :fee => ["a", [ref1,ref2]]}
- result = @parser_resource.to_resource
+ result = @parser_resource.copy_as_resource
result[:fee].should == ["a", Puppet::Resource.new(:file, "/my/file1"), Puppet::Resource.new(:file, "/my/file2")]
end
diff --git a/spec/unit/pops/model/ast_transformer_spec.rb b/spec/unit/pops/model/ast_transformer_spec.rb
index f2b1c9b56..969e944de 100644
--- a/spec/unit/pops/model/ast_transformer_spec.rb
+++ b/spec/unit/pops/model/ast_transformer_spec.rb
@@ -13,28 +13,42 @@ describe Puppet::Pops::Model::AstTransformer do
it "converts a decimal number to a string Name" do
ast = transform(QNAME_OR_NUMBER("10"))
- ast.should be_kind_of Puppet::Parser::AST::Name
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
ast.value.should == "10"
end
+ it "converts a 0 to a decimal 0" do
+ ast = transform(QNAME_OR_NUMBER("0"))
+
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
+ ast.value.should == "0"
+ end
+
+ it "converts a 00 to an octal 00" do
+ ast = transform(QNAME_OR_NUMBER("0"))
+
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
+ ast.value.should == "0"
+ end
+
it "converts an octal number to a string Name" do
ast = transform(QNAME_OR_NUMBER("020"))
- ast.should be_kind_of Puppet::Parser::AST::Name
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
ast.value.should == "020"
end
it "converts a hex number to a string Name" do
ast = transform(QNAME_OR_NUMBER("0x20"))
- ast.should be_kind_of Puppet::Parser::AST::Name
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
ast.value.should == "0x20"
end
it "converts an unknown radix to an error string" do
ast = transform(Puppet::Pops::Model::Factory.new(Puppet::Pops::Model::LiteralNumber, 3, 2))
- ast.should be_kind_of Puppet::Parser::AST::Name
+ ast.should be_kind_of(Puppet::Parser::AST::Name)
ast.value.should == "bad radix:3"
end
end
diff --git a/spec/unit/pops/parser/lexer_spec.rb b/spec/unit/pops/parser/lexer_spec.rb
index 985807261..71010c033 100755
--- a/spec/unit/pops/parser/lexer_spec.rb
+++ b/spec/unit/pops/parser/lexer_spec.rb
@@ -154,7 +154,7 @@ describe Puppet::Pops::Parser::Lexer::TOKENS do
:LBRACK => '[',
:RBRACK => ']',
# :LBRACE => '{',
- :RBRACE => '}',
+# :RBRACE => '}',
:LPAREN => '(',
:RPAREN => ')',
:EQUALS => '=',
@@ -232,7 +232,7 @@ describe Puppet::Pops::Parser::Lexer::TOKENS do
# These tokens' strings don't matter, just that the tokens exist.
[:STRING, :DQPRE, :DQMID, :DQPOST, :BOOLEAN, :NAME, :NUMBER, :COMMENT, :MLCOMMENT,
- :LBRACE, :LAMBDA,
+ :LBRACE, :RBRACE,
:RETURN, :SQUOTE, :DQUOTE, :VARIABLE].each do |name|
it "should have a token named #{name.to_s}" do
Puppet::Pops::Parser::Lexer::TOKENS[name].should_not be_nil
@@ -583,7 +583,24 @@ describe Puppet::Pops::Parser::Lexer,"when lexing strings" do
%q[""] => [[:STRING,""]],
%q["123 456 789 0"] => [[:STRING,"123 456 789 0"]],
%q["${123} 456 $0"] => [[:DQPRE,""],[:VARIABLE,"123"],[:DQMID," 456 "],[:VARIABLE,"0"],[:DQPOST,""]],
- %q["$foo::::bar"] => [[:DQPRE,""],[:VARIABLE,"foo"],[:DQPOST,"::::bar"]]
+ %q["$foo::::bar"] => [[:DQPRE,""],[:VARIABLE,"foo"],[:DQPOST,"::::bar"]],
+ # Keyword variables
+ %q["$true"] => [[:DQPRE,""],[:VARIABLE, "true"],[:DQPOST,""]],
+ %q["$false"] => [[:DQPRE,""],[:VARIABLE, "false"],[:DQPOST,""]],
+ %q["$if"] => [[:DQPRE,""],[:VARIABLE, "if"],[:DQPOST,""]],
+ %q["$case"] => [[:DQPRE,""],[:VARIABLE, "case"],[:DQPOST,""]],
+ %q["$unless"] => [[:DQPRE,""],[:VARIABLE, "unless"],[:DQPOST,""]],
+ %q["$undef"] => [[:DQPRE,""],[:VARIABLE, "undef"],[:DQPOST,""]],
+ # Expressions
+ %q["${true}"] => [[:DQPRE,""],[:BOOLEAN, true],[:DQPOST,""]],
+ %q["${false}"] => [[:DQPRE,""],[:BOOLEAN, false],[:DQPOST,""]],
+ %q["${undef}"] => [[:DQPRE,""],:UNDEF,[:DQPOST,""]],
+ %q["${if true {false}}"] => [[:DQPRE,""],:IF,[:BOOLEAN, true], :LBRACE, [:BOOLEAN, false], :RBRACE, [:DQPOST,""]],
+ %q["${unless true {false}}"] => [[:DQPRE,""],:UNLESS,[:BOOLEAN, true], :LBRACE, [:BOOLEAN, false], :RBRACE, [:DQPOST,""]],
+ %q["${case true {true:{false}}}"] => [
+ [:DQPRE,""],:CASE,[:BOOLEAN, true], :LBRACE, [:BOOLEAN, true], :COLON, :LBRACE, [:BOOLEAN, false],
+ :RBRACE, :RBRACE, [:DQPOST,""]],
+ %q[{ "${a}" => 1 }] => [ :LBRACE, [:DQPRE,""], [:VARIABLE,"a"], [:DQPOST,""], :FARROW, [:NAME,"1"], :RBRACE ],
}.each { |src,expected_result|
it "should handle #{src} correctly" do
EgrammarLexerSpec.tokens_scanned_from(src).should be_like(*expected_result)
@@ -742,7 +759,7 @@ describe "Puppet::Pops::Parser::Lexer in the old tests" do
it "should end variables at `-`" do
EgrammarLexerSpec.tokens_scanned_from('$hyphenated-variable').
- should be_like [:VARIABLE, "hyphenated"], [:MINUS, '-'], [:NAME, 'variable']
+ should be_like([:VARIABLE, "hyphenated"], [:MINUS, '-'], [:NAME, 'variable'])
end
it "should not include whitespace in a variable" do
@@ -769,7 +786,7 @@ describe "when trying to lex a non-existent file" do
it "should return an empty list of tokens" do
lexer = Puppet::Pops::Parser::Lexer.new
lexer.file = nofile = tmpfile('lexer')
- File.exists?(nofile).should == false
+ Puppet::FileSystem::File.exist?(nofile).should == false
lexer.fullscan.should == [[false,false]]
end
diff --git a/spec/unit/pops/parser/parse_calls_spec.rb b/spec/unit/pops/parser/parse_calls_spec.rb
index 647d0e16c..800a15bec 100644
--- a/spec/unit/pops/parser/parse_calls_spec.rb
+++ b/spec/unit/pops/parser/parse_calls_spec.rb
@@ -81,16 +81,16 @@ describe "egrammar parsing function calls" do
dump(parse("$a.foo")).should == "(call-method (. $a foo))"
end
- it "$a.foo {|| }" do
+ it "$a.foo || { }" do
dump(parse("$a.foo || { }")).should == "(call-method (. $a foo) (lambda ()))"
end
- it "$a.foo {|$x| }" do
- dump(parse("$a.foo {|$x| }")).should == "(call-method (. $a foo) (lambda (parameters x) ()))"
+ it "$a.foo |$x| { }" do
+ dump(parse("$a.foo |$x|{ }")).should == "(call-method (. $a foo) (lambda (parameters x) ()))"
end
- it "$a.foo {|$x| }" do
- dump(parse("$a.foo {|$x| $b = $x}")).should ==
+ it "$a.foo |$x|{ }" do
+ dump(parse("$a.foo |$x|{ $b = $x}")).should ==
"(call-method (. $a foo) (lambda (parameters x) (block (= $b $x))))"
end
end
diff --git a/spec/unit/pops/transformer/transform_calls_spec.rb b/spec/unit/pops/transformer/transform_calls_spec.rb
index f2303db5b..969a2d7b8 100644
--- a/spec/unit/pops/transformer/transform_calls_spec.rb
+++ b/spec/unit/pops/transformer/transform_calls_spec.rb
@@ -60,20 +60,20 @@ describe "transformation to Puppet AST for function calls" do
astdump(parse("$a.foo")).should == "(call-method (. $a foo))"
end
- it "$a.foo {|| }" do
+ it "$a.foo ||{ }" do
astdump(parse("$a.foo || { }")).should == "(call-method (. $a foo) (lambda ()))"
end
- it "$a.foo {|| []} # check transformation to block with empty array" do
- astdump(parse("$a.foo || { []}")).should == "(call-method (. $a foo) (lambda (block ([]))))"
+ it "$a.foo ||{[]} # check transformation to block with empty array" do
+ astdump(parse("$a.foo || {[]}")).should == "(call-method (. $a foo) (lambda (block ([]))))"
end
it "$a.foo {|$x| }" do
- astdump(parse("$a.foo {|$x| }")).should == "(call-method (. $a foo) (lambda (parameters x) ()))"
+ astdump(parse("$a.foo |$x| { }")).should == "(call-method (. $a foo) (lambda (parameters x) ()))"
end
- it "$a.foo {|$x| $b = $x}" do
- astdump(parse("$a.foo {|$x| $b = $x}")).should ==
+ it "$a.foo |$x| { $b = $x}" do
+ astdump(parse("$a.foo |$x| { $b = $x}")).should ==
"(call-method (. $a foo) (lambda (parameters x) (block (= $b $x))))"
end
end
diff --git a/spec/unit/pops/transformer/transform_containers_spec.rb b/spec/unit/pops/transformer/transform_containers_spec.rb
index 682860fe1..8c65e2bcc 100644
--- a/spec/unit/pops/transformer/transform_containers_spec.rb
+++ b/spec/unit/pops/transformer/transform_containers_spec.rb
@@ -154,12 +154,12 @@ describe "transformation to Puppet AST for containers" do
it "node foo inherits 'bar' {}" do
# AST can not differentiate between bare word and string
- astdump(parse("node foo inherits 'bar' {}")).should == "(node (matches 'foo') (parent 'bar') ())"
+ astdump(parse("node foo inherits 'bar' {}")).should == "(node (matches 'foo') (parent bar) ())"
end
it "node foo inherits default {}" do
# AST can not differentiate between bare word and string
- astdump(parse("node foo inherits default {}")).should == "(node (matches 'foo') (parent :default) ())"
+ astdump(parse("node foo inherits default {}")).should == "(node (matches 'foo') (parent default) ())"
end
it "node /web.*/ {}" do
diff --git a/spec/unit/pops/validator/validator_spec.rb b/spec/unit/pops/validator/validator_spec.rb
new file mode 100644
index 000000000..d54d2ca61
--- /dev/null
+++ b/spec/unit/pops/validator/validator_spec.rb
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+require 'puppet/pops'
+require 'puppet_spec/pops'
+
+# relative to this spec file (./) does not work as this file is loaded by rspec
+require File.join(File.dirname(__FILE__), '../parser/parser_rspec_helper')
+
+describe "validating 3x" do
+ include ParserRspecHelper
+ include PuppetSpec::Pops
+
+ let(:acceptor) { Puppet::Pops::Validation::Acceptor.new() }
+ let(:validator) { Puppet::Pops::Validation::ValidatorFactory_3_1.new().validator(acceptor) }
+
+ def validate(model)
+ validator.validate(model)
+ acceptor
+ end
+
+ it 'should raise error for illegal names' do
+ expect(validate(fqn('Aaa'))).to have_issue(Puppet::Pops::Issues::ILLEGAL_NAME)
+ expect(validate(fqn('AAA'))).to have_issue(Puppet::Pops::Issues::ILLEGAL_NAME)
+ end
+
+ it 'should raise error for illegal variable names' do
+ expect(validate(fqn('Aaa').var())).to have_issue(Puppet::Pops::Issues::ILLEGAL_NAME)
+ expect(validate(fqn('AAA').var())).to have_issue(Puppet::Pops::Issues::ILLEGAL_NAME)
+ end
+
+end \ No newline at end of file
diff --git a/spec/unit/provider/augeas/augeas_spec.rb b/spec/unit/provider/augeas/augeas_spec.rb
index e75a0d36e..9b6e88ce8 100755
--- a/spec/unit/provider/augeas/augeas_spec.rb
+++ b/spec/unit/provider/augeas/augeas_spec.rb
@@ -276,6 +276,61 @@ describe provider_class do
@provider.need_to_run?.should == true
end
+ describe "performing numeric comparisons (#22617)" do
+ it "should return true when a get string compare is true" do
+ @resource[:onlyif] = "get bpath > a"
+ @augeas.stubs("get").returns("b")
+ @provider.need_to_run?.should == true
+ end
+
+ it "should return false when a get string compare is false" do
+ @resource[:onlyif] = "get a19path > a2"
+ @augeas.stubs("get").returns("a19")
+ @provider.need_to_run?.should == false
+ end
+
+ it "should return true when a get int gt compare is true" do
+ @resource[:onlyif] = "get path19 > 2"
+ @augeas.stubs("get").returns("19")
+ @provider.need_to_run?.should == true
+ end
+
+ it "should return true when a get int ge compare is true" do
+ @resource[:onlyif] = "get path19 >= 2"
+ @augeas.stubs("get").returns("19")
+ @provider.need_to_run?.should == true
+ end
+
+ it "should return true when a get int lt compare is true" do
+ @resource[:onlyif] = "get path2 < 19"
+ @augeas.stubs("get").returns("2")
+ @provider.need_to_run?.should == true
+ end
+
+ it "should return false when a get int le compare is false" do
+ @resource[:onlyif] = "get path39 <= 4"
+ @augeas.stubs("get").returns("39")
+ @provider.need_to_run?.should == false
+ end
+ end
+ describe "performing is_numeric checks (#22617)" do
+ it "should return false for nil" do
+ @provider.is_numeric?(nil).should == false
+ end
+ it "should return true for Fixnums" do
+ @provider.is_numeric?(9).should == true
+ end
+ it "should return true for numbers in Strings" do
+ @provider.is_numeric?('9').should == true
+ end
+ it "should return false for non-number Strings" do
+ @provider.is_numeric?('x9').should == false
+ end
+ it "should return false for other types" do
+ @provider.is_numeric?([true]).should == false
+ end
+ end
+
it "should return false when a get filter does not match" do
@resource[:onlyif] = "get path == another value"
@augeas.stubs("get").returns("value")
@@ -619,7 +674,7 @@ describe provider_class do
link = tmpfile('link')
target = tmpfile('target')
FileUtils.touch(target)
- FileUtils.symlink(target, link)
+ Puppet::FileSystem::File.new(target).symlink(link)
resource = Puppet::Type.type(:augeas).new(
:name => 'test',
@@ -634,7 +689,7 @@ describe provider_class do
catalog.apply
File.ftype(link).should == 'link'
- File.readlink(link).should == target
+ Puppet::FileSystem::File.new(link).readlink().should == target
File.read(target).should =~ /PermitRootLogin no/
end
end
diff --git a/spec/unit/provider/exec/posix_spec.rb b/spec/unit/provider/exec/posix_spec.rb
index 39cc10b41..7c4982fcc 100755
--- a/spec/unit/provider/exec/posix_spec.rb
+++ b/spec/unit/provider/exec/posix_spec.rb
@@ -64,7 +64,7 @@ describe Puppet::Type.type(:exec).provider(:posix) do
provider.resource[:path] = [File.dirname(command)]
filename = File.basename(command)
- Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == filename) && (arguments.is_a? Hash) }
+ Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == filename) && (arguments.is_a? Hash) }.returns(Puppet::Util::Execution::ProcessOutput.new('', 0))
provider.run(filename)
end
@@ -95,7 +95,7 @@ describe Puppet::Type.type(:exec).provider(:posix) do
provider.resource[:path] = ['/bogus/bin']
command = make_exe
- Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == "#{command} bar --sillyarg=true --blah") && (arguments.is_a? Hash) }
+ Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == "#{command} bar --sillyarg=true --blah") && (arguments.is_a? Hash) }.returns(Puppet::Util::Execution::ProcessOutput.new('', 0))
provider.run("#{command} bar --sillyarg=true --blah")
end
@@ -110,11 +110,16 @@ describe Puppet::Type.type(:exec).provider(:posix) do
provider.resource[:environment] = ['WHATEVER=/something/else', 'WHATEVER=/foo']
command = make_exe
- Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == command) && (arguments.is_a? Hash) }
+ Puppet::Util::Execution.expects(:execute).with { |cmdline, arguments| (cmdline == command) && (arguments.is_a? Hash) }.returns(Puppet::Util::Execution::ProcessOutput.new('', 0))
provider.run(command)
@logs.map {|l| "#{l.level}: #{l.message}" }.should == ["warning: Overriding environment setting 'WHATEVER' with '/foo'"]
end
+ it "should set umask before execution if umask parameter is in use" do
+ provider.resource[:umask] = '0027'
+ Puppet::Util.expects(:withumask).with(0027)
+ provider.run(provider.resource[:command])
+ end
describe "posix locale settings", :unless => Puppet.features.microsoft_windows? do
# a sentinel value that we can use to emulate what locale environment variables might be set to on an international
diff --git a/spec/unit/provider/file/posix_spec.rb b/spec/unit/provider/file/posix_spec.rb
index e84d23a5a..48eaae30a 100755
--- a/spec/unit/provider/file/posix_spec.rb
+++ b/spec/unit/provider/file/posix_spec.rb
@@ -85,7 +85,7 @@ describe Puppet::Type.type(:file).provider(:posix), :if => Puppet.features.posix
describe "#owner" do
it "should return the uid of the file owner" do
FileUtils.touch(path)
- owner = File.stat(path).uid
+ owner = Puppet::FileSystem::File.new(path).stat.uid
provider.owner.should == owner
end
@@ -178,7 +178,7 @@ describe Puppet::Type.type(:file).provider(:posix), :if => Puppet.features.posix
describe "#group" do
it "should return the gid of the file group" do
FileUtils.touch(path)
- group = File.stat(path).gid
+ group = Puppet::FileSystem::File.new(path).stat.gid
provider.group.should == group
end
diff --git a/spec/unit/provider/group/windows_adsi_spec.rb b/spec/unit/provider/group/windows_adsi_spec.rb
index 21b967509..d28601172 100644
--- a/spec/unit/provider/group/windows_adsi_spec.rb
+++ b/spec/unit/provider/group/windows_adsi_spec.rb
@@ -24,12 +24,64 @@ describe Puppet::Type.type(:group).provider(:windows_adsi) do
names = ['group1', 'group2', 'group3']
stub_groups = names.map{|n| stub(:name => n)}
- connection.stubs(:execquery).with("select name from win32_group").returns stub_groups
+ connection.stubs(:execquery).with('select name from win32_group where localaccount = "TRUE"').returns stub_groups
described_class.instances.map(&:name).should =~ names
end
end
+ describe "group type :members property helpers", :if => Puppet.features.microsoft_windows? do
+
+ let(:user1) { stub(:account => 'user1', :domain => '.', :to_s => 'user1sid') }
+ let(:user2) { stub(:account => 'user2', :domain => '.', :to_s => 'user2sid') }
+
+ before :each do
+ Puppet::Util::Windows::Security.stubs(:name_to_sid_object).with('user1').returns(user1)
+ Puppet::Util::Windows::Security.stubs(:name_to_sid_object).with('user2').returns(user2)
+ end
+
+ describe "#members_insync?" do
+ it "should return false when current is nil" do
+ provider.members_insync?(nil, ['user2']).should be_false
+ end
+ it "should return false when should is nil" do
+ provider.members_insync?(['user1'], nil).should be_false
+ end
+ it "should return false for differing lists of members" do
+ provider.members_insync?(['user1'], ['user2']).should be_false
+ provider.members_insync?(['user1'], []).should be_false
+ provider.members_insync?([], ['user2']).should be_false
+ end
+ it "should return true for same lists of members" do
+ provider.members_insync?(['user1', 'user2'], ['user1', 'user2']).should be_true
+ end
+ it "should return true for same lists of unordered members" do
+ provider.members_insync?(['user1', 'user2'], ['user2', 'user1']).should be_true
+ end
+ it "should return true for same lists of members irrespective of duplicates" do
+ provider.members_insync?(['user1', 'user2', 'user2'], ['user2', 'user1', 'user1']).should be_true
+ end
+ end
+
+ describe "#members_to_s" do
+ it "should return an empty string on non-array input" do
+ [Object.new, {}, 1, :symbol, ''].each do |input|
+ provider.members_to_s(input).should be_empty
+ end
+ end
+ it "should return an empty string on empty or nil users" do
+ provider.members_to_s([]).should be_empty
+ provider.members_to_s(nil).should be_empty
+ end
+ it "should return a user string like DOMAIN\\USER" do
+ provider.members_to_s(['user1']).should == '.\user1'
+ end
+ it "should return a user string like DOMAIN\\USER,DOMAIN2\\USER2" do
+ provider.members_to_s(['user1', 'user2']).should == '.\user1,.\user2'
+ end
+ end
+ end
+
describe "when managing members" do
it "should be able to provide a list of members" do
provider.group.stubs(:members).returns ['user1', 'user2', 'user3']
@@ -37,11 +89,22 @@ describe Puppet::Type.type(:group).provider(:windows_adsi) do
provider.members.should =~ ['user1', 'user2', 'user3']
end
- it "should be able to set group members" do
+ it "should be able to set group members", :if => Puppet.features.microsoft_windows? do
provider.group.stubs(:members).returns ['user1', 'user2']
- provider.group.expects(:remove_members).with('user1')
- provider.group.expects(:add_members).with('user3')
+ member_sids = [
+ stub(:account => 'user1', :domain => 'testcomputername'),
+ stub(:account => 'user2', :domain => 'testcomputername'),
+ stub(:account => 'user3', :domain => 'testcomputername'),
+ ]
+
+ provider.group.stubs(:member_sids).returns(member_sids[0..1])
+
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('user2').returns(member_sids[1])
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('user3').returns(member_sids[2])
+
+ provider.group.expects(:remove_member_sids).with(member_sids[0])
+ provider.group.expects(:add_member_sids).with(member_sids[2])
provider.members = ['user2', 'user3']
end
@@ -97,4 +160,8 @@ describe Puppet::Type.type(:group).provider(:windows_adsi) do
provider.expects(:fail).with { |msg| msg =~ /gid is read-only/ }
provider.send(:gid=, 500)
end
+
+ it "should prefer the domain component from the resolved SID", :if => Puppet.features.microsoft_windows? do
+ provider.members_to_s(['.\Administrators']).should == 'BUILTIN\Administrators'
+ end
end
diff --git a/spec/unit/provider/nameservice/directoryservice_spec.rb b/spec/unit/provider/nameservice/directoryservice_spec.rb
index e7fdcbef5..fbb74d0f3 100755
--- a/spec/unit/provider/nameservice/directoryservice_spec.rb
+++ b/spec/unit/provider/nameservice/directoryservice_spec.rb
@@ -110,7 +110,7 @@ describe 'DirectoryService password behavior' do
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)
+ Puppet::FileSystem::File.expects(:exist?).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)
@@ -126,7 +126,7 @@ describe 'DirectoryService password behavior' do
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)
+ Puppet::FileSystem::File.expects(:exist?).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)
@@ -138,7 +138,7 @@ describe 'DirectoryService password behavior' do
it '[#13686] should handle an empty ShadowHashData field in the users plist' do
subject.expects(:convert_xml_to_binary).returns(binary_plist)
- File.expects(:exists?).with(plist_path).once.returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(plist_path).once.returns(true)
Plist.expects(:parse_xml).returns({'ShadowHashData' => nil})
subject.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout', plist_path)
subject.expects(:plutil).with('-convert', 'binary1', plist_path)
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index 5e75a569f..5d7b3e4e6 100755
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_spec.rb
@@ -63,7 +63,7 @@ Version table:
it "should preseed with the provided responsefile when preseeding is called for" do
@resource.expects(:[]).with(:responsefile).returns "/my/file"
- FileTest.expects(:exist?).with("/my/file").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/my/file").returns true
@provider.expects(:info)
@provider.expects(:preseed).with("/my/file")
diff --git a/spec/unit/provider/package/aptrpm_spec.rb b/spec/unit/provider/package/aptrpm_spec.rb
index 6c77bee3a..83d343242 100755
--- a/spec/unit/provider/package/aptrpm_spec.rb
+++ b/spec/unit/provider/package/aptrpm_spec.rb
@@ -19,7 +19,7 @@ describe Puppet::Type.type(:package).provider(:aptrpm) do
def rpm
pkg.provider.expects(:rpm).
with('-q', 'faff', '--nosignature', '--nodigest', '--qf',
- "'%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH} :DESC: %{SUMMARY}\\n'")
+ "%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH} :DESC: %{SUMMARY}\\n")
end
it "should report absent packages" do
diff --git a/spec/unit/provider/package/msi_spec.rb b/spec/unit/provider/package/msi_spec.rb
index 50ff40deb..192b0a749 100755
--- a/spec/unit/provider/package/msi_spec.rb
+++ b/spec/unit/provider/package/msi_spec.rb
@@ -24,9 +24,8 @@ describe Puppet::Type.type(:package).provider(:msi) do
MsiPackage.stubs(:installer).returns(installer)
end
- before :each do
- # make sure we never try to execute msiexec
- provider.expects(:execute).never
+ def expect_execute(command, status)
+ provider.expects(:execute).with(command, execute_options).returns(Puppet::Util::Execution::ProcessOutput.new('',status))
end
describe 'provider features' do
@@ -38,6 +37,7 @@ describe Puppet::Type.type(:package).provider(:msi) do
describe 'on Windows', :as_platform => :windows do
it 'should not be the default provider' do
+ # provider.expects(:execute).never
Puppet::Type.type(:package).defaultprovider.should_not == subject.class
end
end
@@ -90,9 +90,7 @@ describe Puppet::Type.type(:package).provider(:msi) do
end
context '#install' do
- before :each do
- provider.stubs(:execute)
- end
+ let (:command) { "msiexec.exe /qn /norestart /i #{source}" }
it 'should require the source parameter' do
resource = Puppet::Type.type(:package).new(:name => name, :provider => :msi)
@@ -104,40 +102,27 @@ describe Puppet::Type.type(:package).provider(:msi) do
it 'should install using the source and install_options' do
resource[:install_options] = { 'INSTALLDIR' => 'C:\mysql-5.1' }
-
- provider.expects(:execute).with("msiexec.exe /qn /norestart /i #{source} INSTALLDIR=C:\\mysql-5.1", execute_options)
- provider.expects(:exit_status).returns(0)
-
- provider.install
- end
-
- it 'should warn if the package requests a reboot' do
- provider.stubs(:exit_status).returns(194)
-
- provider.expects(:warning).with('The package requested a reboot to finish the operation.')
+ expect_execute("#{command} INSTALLDIR=C:\\mysql-5.1", 0)
provider.install
end
it 'should warn if reboot initiated' do
- provider.stubs(:exit_status).returns(1641)
-
+ expect_execute(command, 1641)
provider.expects(:warning).with('The package installed successfully and the system is rebooting now.')
provider.install
end
it 'should warn if reboot required' do
- provider.stubs(:exit_status).returns(3010)
-
+ expect_execute(command, 3010)
provider.expects(:warning).with('The package installed successfully, but the system must be rebooted.')
provider.install
end
it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do
- provider.stubs(:execute)
- provider.stubs(:exit_status).returns(5)
+ expect_execute(command, 5)
expect do
provider.install
@@ -146,6 +131,9 @@ describe Puppet::Type.type(:package).provider(:msi) do
end
context '#uninstall' do
+
+ let (:command) { "msiexec.exe /qn /norestart /x #{productcode}" }
+
before :each do
resource[:ensure] = :absent
provider.set(:productcode => productcode)
@@ -159,42 +147,27 @@ describe Puppet::Type.type(:package).provider(:msi) do
end
it 'should uninstall using the productcode' do
- provider.expects(:execute).with("msiexec.exe /qn /norestart /x #{productcode}", execute_options)
- provider.expects(:exit_status).returns(0)
-
- provider.uninstall
- end
-
- it 'should warn if the package requests a reboot' do
- provider.stubs(:execute)
- provider.stubs(:exit_status).returns(194)
-
- provider.expects(:warning).with('The package requested a reboot to finish the operation.')
+ expect_execute(command, 0)
provider.uninstall
end
it 'should warn if reboot initiated' do
- provider.stubs(:execute)
- provider.stubs(:exit_status).returns(1641)
-
+ expect_execute(command, 1641)
provider.expects(:warning).with('The package uninstalled successfully and the system is rebooting now.')
provider.uninstall
end
it 'should warn if reboot required' do
- provider.stubs(:execute)
- provider.stubs(:exit_status).returns(3010)
-
+ expect_execute(command, 3010)
provider.expects(:warning).with('The package uninstalled successfully, but the system must be rebooted.')
provider.uninstall
end
it 'should fail otherwise', :if => Puppet.features.microsoft_windows? do
- provider.stubs(:execute)
- provider.stubs(:exit_status).returns(5)
+ expect_execute(command, 5)
expect do
provider.uninstall
diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb
index 5a7ef7b46..48ec4bedb 100755
--- a/spec/unit/provider/package/openbsd_spec.rb
+++ b/spec/unit/provider/package/openbsd_spec.rb
@@ -10,7 +10,7 @@ describe provider_class do
def expect_read_from_pkgconf(lines)
pkgconf = stub(:readlines => lines)
- File.expects(:exist?).with('/etc/pkg.conf').returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with('/etc/pkg.conf').returns(true)
File.expects(:open).with('/etc/pkg.conf', 'rb').returns(pkgconf)
end
@@ -76,7 +76,7 @@ describe provider_class do
context "#install" do
it "should fail if the resource doesn't have a source" do
- File.expects(:exist?).with('/etc/pkg.conf').returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with('/etc/pkg.conf').returns(false)
expect {
provider.install
@@ -84,7 +84,7 @@ describe provider_class do
end
it "should fail if /etc/pkg.conf exists, but is not readable" do
- File.expects(:exist?).with('/etc/pkg.conf').returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with('/etc/pkg.conf').returns(true)
File.expects(:open).with('/etc/pkg.conf', 'rb').raises(Errno::EACCES)
expect {
diff --git a/spec/unit/provider/package/rpm_spec.rb b/spec/unit/provider/package/rpm_spec.rb
index e438b51a5..e81abafde 100755
--- a/spec/unit/provider/package/rpm_spec.rb
+++ b/spec/unit/provider/package/rpm_spec.rb
@@ -20,7 +20,8 @@ describe provider_class do
let(:resource) do
Puppet::Type.type(:package).new(
:name => resource_name,
- :ensure => :installed
+ :ensure => :installed,
+ :provider => 'rpm'
)
end
@@ -30,7 +31,7 @@ describe provider_class do
provider
end
- let(:nevra_format) { %Q{'%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH} :DESC: %{SUMMARY}\\n'} }
+ let(:nevra_format) { %Q{%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH} :DESC: %{SUMMARY}\\n} }
let(:execute_options) do
{:failonfail => true, :combine => true, :custom_environment => {}}
end
@@ -47,7 +48,7 @@ describe provider_class do
describe "self.instances" do
describe "with a modern version of RPM" do
it "should include all the modern flags" do
- Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf #{nevra_format}").yields(packages)
+ Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf '#{nevra_format}'").yields(packages)
installed_packages = subject.instances
end
@@ -56,7 +57,7 @@ describe provider_class do
describe "with a version of RPM < 4.1" do
let(:rpm_version) { "RPM version 4.0.2\n" }
it "should exclude the --nosignature flag" do
- Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nodigest --qf #{nevra_format}").yields(packages)
+ Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nodigest --qf '#{nevra_format}'").yields(packages)
installed_packages = subject.instances
end
@@ -65,14 +66,14 @@ describe provider_class do
describe "with a version of RPM < 4.0.2" do
let(:rpm_version) { "RPM version 3.0.5\n" }
it "should exclude the --nodigest flag" do
- Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --qf #{nevra_format}").yields(packages)
+ Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --qf '#{nevra_format}'").yields(packages)
installed_packages = subject.instances
end
end
it "returns an array of packages" do
- Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf #{nevra_format}").yields(packages)
+ Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf '#{nevra_format}'").yields(packages)
installed_packages = subject.instances
@@ -138,23 +139,40 @@ describe provider_class do
describe "when not already installed" do
it "should only include the '-i' flag" do
- Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", "-i", '/path/to/package'], execute_options)
+ Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", ["-i"], '/path/to/package'], execute_options)
provider.install
end
- end
+ end
- describe "when an older version is installed" do
- before(:each) do
- # Force the provider to think a version of the package is already installed
- # This is real hacky. I'm sorry. --jeffweiss 25 Jan 2013
- provider.instance_variable_get('@property_hash')[:ensure] = '1.2.3.3'
- end
+ describe "when installed with options" do
+ let(:resource) do
+ Puppet::Type.type(:package).new(
+ :name => resource_name,
+ :ensure => :installed,
+ :provider => 'rpm',
+ :source => '/path/to/package',
+ :install_options => ['-D', {'--test' => 'value'}, '-Q']
+ )
+ end
- it "should include the '-U --oldpackage' flags" do
- Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", ["-U", "--oldpackage"], '/path/to/package'], execute_options)
+ it "should include the options" do
+ Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", ["-i", "-D", "--test=value", "-Q"], '/path/to/package'], execute_options)
provider.install
- end
- end
+ end
+ end
+
+ describe "when an older version is installed" do
+ before(:each) do
+ # Force the provider to think a version of the package is already installed
+ # This is real hacky. I'm sorry. --jeffweiss 25 Jan 2013
+ provider.instance_variable_get('@property_hash')[:ensure] = '1.2.3.3'
+ end
+
+ it "should include the '-U --oldpackage' flags" do
+ Puppet::Util::Execution.expects(:execute).with(["/bin/rpm", ["-U", "--oldpackage"], '/path/to/package'], execute_options)
+ provider.install
+ end
+ end
end
describe "#latest" do
@@ -268,6 +286,31 @@ describe provider_class do
end
end
+ describe "#install_options" do
+ it "should return empty array by default" do
+ provider.install_options.should == []
+ end
+
+ it "should return install_options when set" do
+ provider.resource[:install_options] = ['-n']
+ provider.install_options.should == ['-n']
+ end
+
+ it "should return multiple install_options when set" do
+ provider.resource[:install_options] = ['-L', '/opt/puppet']
+ provider.install_options.should == ['-L', '/opt/puppet']
+ end
+
+ it 'should return install_options when set as hash' do
+ provider.resource[:install_options] = { '-Darch' => 'vax' }
+ provider.install_options.should == ['-Darch=vax']
+ end
+ it 'should return install_options when an array with hashes' do
+ provider.resource[:install_options] = [ '-L', { '-Darch' => 'vax' }]
+ provider.install_options.should == ['-L', '-Darch=vax']
+ end
+ end
+
describe ".nodigest" do
{ '4.0' => nil,
'4.0.1' => nil,
diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb
index d07d584de..4541f9ea7 100755
--- a/spec/unit/provider/package/windows_spec.rb
+++ b/spec/unit/provider/package/windows_spec.rb
@@ -14,8 +14,7 @@ describe Puppet::Type.type(:package).provider(:windows) do
end
def expect_execute(command, status)
- provider.expects(:execute).with(command, execute_options)
- provider.expects(:exit_status).returns(status)
+ provider.expects(:execute).with(command, execute_options).returns(Puppet::Util::Execution::ProcessOutput.new('',status))
end
describe 'provider features' do
@@ -23,6 +22,7 @@ describe Puppet::Type.type(:package).provider(:windows) do
it { should be_uninstallable }
it { should be_install_options }
it { should be_uninstall_options }
+ it { should be_versionable }
end
describe 'on Windows', :if => Puppet.features.microsoft_windows? do
@@ -36,17 +36,19 @@ describe Puppet::Type.type(:package).provider(:windows) do
pkg1 = stub('pkg1')
pkg2 = stub('pkg2')
- prov1 = stub('prov1', :name => 'pkg1', :package => pkg1)
- prov2 = stub('prov2', :name => 'pkg2', :package => pkg2)
+ prov1 = stub('prov1', :name => 'pkg1', :version => '1.0.0', :package => pkg1)
+ prov2 = stub('prov2', :name => 'pkg2', :version => nil, :package => pkg2)
Puppet::Provider::Package::Windows::Package.expects(:map).multiple_yields([prov1], [prov2]).returns([prov1, prov2])
providers = provider.class.instances
providers.count.should == 2
providers[0].name.should == 'pkg1'
+ providers[0].version.should == '1.0.0'
providers[0].package.should == pkg1
providers[1].name.should == 'pkg2'
+ providers[1].version.should be_nil
providers[1].package.should == pkg2
end
@@ -59,13 +61,21 @@ describe Puppet::Type.type(:package).provider(:windows) do
context '#query' do
it 'should return the hash of the matched packaged' do
- pkg = mock(:name => 'pkg1')
+ pkg = mock(:name => 'pkg1', :version => nil)
pkg.expects(:match?).returns(true)
Puppet::Provider::Package::Windows::Package.expects(:find).yields(pkg)
provider.query.should == { :name => 'pkg1', :ensure => :installed, :provider => :windows }
end
+ it 'should include the version string when present' do
+ pkg = mock(:name => 'pkg1', :version => '1.0.0')
+ pkg.expects(:match?).returns(true)
+ Puppet::Provider::Package::Windows::Package.expects(:find).yields(pkg)
+
+ provider.query.should == { :name => 'pkg1', :ensure => '1.0.0', :provider => :windows }
+ end
+
it 'should return nil if no package was found' do
Puppet::Provider::Package::Windows::Package.expects(:find)
@@ -102,13 +112,6 @@ describe Puppet::Type.type(:package).provider(:windows) do
provider.install
end
- it 'should warn if the package requests a reboot' do
- expect_execute(command, 194)
- provider.expects(:warning).with('The package requested a reboot to finish the operation.')
-
- provider.install
- end
-
it 'should warn if reboot initiated' do
expect_execute(command, 1641)
provider.expects(:warning).with('The package installed successfully and the system is rebooting now.')
@@ -161,13 +164,6 @@ describe Puppet::Type.type(:package).provider(:windows) do
provider.uninstall
end
- it 'should warn if the package requests a reboot' do
- expect_execute(command, 194)
- provider.expects(:warning).with('The package requested a reboot to finish the operation.')
-
- provider.uninstall
- end
-
it 'should warn if reboot initiated' do
expect_execute(command, 1641)
provider.expects(:warning).with('The package uninstalled successfully and the system is rebooting now.')
diff --git a/spec/unit/provider/package/yum_spec.rb b/spec/unit/provider/package/yum_spec.rb
index 7a019bea7..c5d89ae60 100755
--- a/spec/unit/provider/package/yum_spec.rb
+++ b/spec/unit/provider/package/yum_spec.rb
@@ -153,7 +153,7 @@ _pkg mysummaryless 0 1.2.3.4 5.el4 noarch
end
def expect_execpipe_to_provide_package_info_for_an_rpm_query
- Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf #{nevra_format}").yields(packages)
+ Puppet::Util::Execution.expects(:execpipe).with("/bin/rpm -qa --nosignature --nodigest --qf '#{nevra_format}'").yields(packages)
end
def expect_python_yumhelper_call_to_return_latest_info
diff --git a/spec/unit/provider/service/base_spec.rb b/spec/unit/provider/service/base_spec.rb
index b78bb0134..9d6a7fdcc 100755
--- a/spec/unit/provider/service/base_spec.rb
+++ b/spec/unit/provider/service/base_spec.rb
@@ -34,7 +34,7 @@ describe "base service provider" do
end
before :each do
- File.unlink(flag) if File.exist?(flag)
+ Puppet::FileSystem::File.unlink(flag) if Puppet::FileSystem::File.exist?(flag)
end
it { should be }
diff --git a/spec/unit/provider/service/daemontools_spec.rb b/spec/unit/provider/service/daemontools_spec.rb
index c538a0ced..4c35e0586 100755
--- a/spec/unit/provider/service/daemontools_spec.rb
+++ b/spec/unit/provider/service/daemontools_spec.rb
@@ -99,9 +99,14 @@ describe provider_class do
end
describe "when enabling" do
- it "should create a symlink between daemon dir and service dir" do
- FileTest.stubs(:symlink?).returns(false)
- File.expects(:symlink).with(File.join(@daemondir,"myservice"), File.join(@servicedir,"myservice")).returns(0)
+ it "should create a symlink between daemon dir and service dir", :if => Puppet.features.manages_symlinks? do
+ daemon_path = File.join(@daemondir, "myservice")
+ stub_daemon = stub(daemon_path, :symlink? => false)
+ Puppet::FileSystem::File.expects(:new).with(daemon_path).returns(stub_daemon)
+ service_path = File.join(@servicedir, "myservice")
+ mock_service = mock(service_path, :symlink? => false)
+ Puppet::FileSystem::File.expects(:new).with(service_path).returns(mock_service)
+ stub_daemon.expects(:symlink).returns(0)
@provider.enable
end
end
@@ -109,16 +114,19 @@ describe provider_class do
describe "when disabling" do
it "should remove the symlink between daemon dir and service dir" do
FileTest.stubs(:directory?).returns(false)
- FileTest.stubs(:symlink?).returns(true)
- File.expects(:unlink).with(File.join(@servicedir,"myservice"))
+ path = File.join(@servicedir,"myservice")
+ mocked_file = mock(path, :symlink? => true)
+ Puppet::FileSystem::File.expects(:new).with(path).returns(mocked_file)
+ Puppet::FileSystem::File.expects(:unlink).with(path)
@provider.stubs(:texecute).returns("")
@provider.disable
end
it "should stop the service" do
FileTest.stubs(:directory?).returns(false)
- FileTest.stubs(:symlink?).returns(true)
- File.stubs(:unlink)
+ mocked_file = mock('anything', :symlink? => true)
+ Puppet::FileSystem::File.expects(:new).returns(mocked_file)
+ Puppet::FileSystem::File.stubs(:unlink)
@provider.expects(:stop)
@provider.disable
end
@@ -134,7 +142,9 @@ describe provider_class do
[true, false].each do |t|
it "should return #{t} if the symlink exists" do
@provider.stubs(:status).returns(:stopped)
- FileTest.stubs(:symlink?).returns(t)
+ path = File.join(@servicedir,"myservice")
+ mocked_file = mock(path, :symlink? => t)
+ Puppet::FileSystem::File.expects(:new).with(path).returns(mocked_file)
@provider.enabled?.should == "#{t}".to_sym
end
diff --git a/spec/unit/provider/service/freebsd_spec.rb b/spec/unit/provider/service/freebsd_spec.rb
index 81e3fc1af..69b923f9a 100755
--- a/spec/unit/provider/service/freebsd_spec.rb
+++ b/spec/unit/provider/service/freebsd_spec.rb
@@ -62,13 +62,13 @@ OUTPUT
end
it "should enable only the selected service" do
- File.stubs(:exists?).with('/etc/rc.conf').returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with('/etc/rc.conf').returns(true)
File.stubs(:read).with('/etc/rc.conf').returns("openntpd_enable=\"NO\"\nntpd_enable=\"NO\"\n")
fh = stub 'fh'
File.stubs(:open).with('/etc/rc.conf', File::WRONLY).yields(fh)
fh.expects(:<<).with("openntpd_enable=\"NO\"\nntpd_enable=\"YES\"\n")
- File.stubs(:exists?).with('/etc/rc.conf.local').returns(false)
- File.stubs(:exists?).with('/etc/rc.conf.d/ntpd').returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).with('/etc/rc.conf.local').returns(false)
+ Puppet::FileSystem::File.stubs(:exist?).with('/etc/rc.conf.d/ntpd').returns(false)
@provider.rc_replace('ntpd', 'ntpd', 'YES')
end
diff --git a/spec/unit/provider/service/gentoo_spec.rb b/spec/unit/provider/service/gentoo_spec.rb
index dab315537..aa802430e 100755
--- a/spec/unit/provider/service/gentoo_spec.rb
+++ b/spec/unit/provider/service/gentoo_spec.rb
@@ -13,7 +13,9 @@ describe Puppet::Type.type(:service).provider(:gentoo) do
# The initprovider (parent of the gentoo provider) does a stat call
# before it even tries to execute an initscript. We use sshd in all the
# tests so make sure it is considered present.
- File.stubs(:stat).with('/etc/init.d/sshd')
+ sshd_path = '/etc/init.d/sshd'
+ stub_file = stub(sshd_path, :stat => stub('stat'))
+ Puppet::FileSystem::File.stubs(:new).with(sshd_path).returns stub_file
end
let :initscripts do
@@ -48,7 +50,6 @@ describe Puppet::Type.type(:service).provider(:gentoo) do
it "should get a list of services from /etc/init.d but exclude helper scripts" do
FileTest.expects(:directory?).with('/etc/init.d').returns true
- File.stubs(:symlink?).returns(false)
Dir.expects(:entries).with('/etc/init.d').returns initscripts
(initscripts - helperscripts).each do |script|
FileTest.expects(:executable?).with("/etc/init.d/#{script}").returns true
@@ -56,6 +57,8 @@ describe Puppet::Type.type(:service).provider(:gentoo) do
helperscripts.each do |script|
FileTest.expects(:executable?).with("/etc/init.d/#{script}").never
end
+
+ Puppet::FileSystem::File.stubs(:new).returns stub('file', :symlink? => false)
described_class.instances.map(&:name).should == [
'alsasound',
'bootmisc',
diff --git a/spec/unit/provider/service/init_spec.rb b/spec/unit/provider/service/init_spec.rb
index e88672b40..896f13ac1 100755
--- a/spec/unit/provider/service/init_spec.rb
+++ b/spec/unit/provider/service/init_spec.rb
@@ -62,12 +62,12 @@ describe Puppet::Type.type(:service).provider(:init) do
described_class.instances.should be_all { |provider| provider.get(:hasstatus) == true }
end
- it "should discard upstart jobs" do
+ it "should discard upstart jobs", :if => Puppet.features.manages_symlinks? do
not_init_service, *valid_services = @services
- File.stubs(:symlink?).returns false
- File.stubs(:symlink?).with("tmp/#{not_init_service}").returns(true)
- File.stubs(:readlink).with("tmp/#{not_init_service}").returns("/lib/init/upstart-job")
-
+ path = "tmp/#{not_init_service}"
+ mocked_file = mock(path, :symlink? => true, :readlink => "/lib/init/upstart-job")
+ Puppet::FileSystem::File.stubs(:new).returns stub('file', :symlink? => false)
+ Puppet::FileSystem::File.expects(:new).with(path).returns(mocked_file)
described_class.instances.map(&:name).should == valid_services
end
@@ -82,7 +82,7 @@ describe Puppet::Type.type(:service).provider(:init) do
describe "when checking valid paths" do
it "should discard paths that do not exist" do
File.expects(:directory?).with(paths[0]).returns false
- File.expects(:exist?).with(paths[0]).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(paths[0]).returns false
File.expects(:directory?).with(paths[1]).returns true
provider.paths.should == [paths[1]]
@@ -90,7 +90,7 @@ describe Puppet::Type.type(:service).provider(:init) do
it "should discard paths that are not directories" do
paths.each do |path|
- File.expects(:exist?).with(path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns true
File.expects(:directory?).with(path).returns false
end
provider.paths.should be_empty
@@ -103,28 +103,28 @@ describe Puppet::Type.type(:service).provider(:init) do
end
it "should be able to find the init script in the service path" do
- File.expects(:exist?).with("#{paths[0]}/myservice").returns true
- File.expects(:exist?).with("#{paths[1]}/myservice").never # first one wins
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[0]}/myservice").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[1]}/myservice").never # first one wins
provider.initscript.should == "/service/path/myservice"
end
it "should be able to find the init script in an alternate service path" do
- File.expects(:exist?).with("#{paths[0]}/myservice").returns false
- File.expects(:exist?).with("#{paths[1]}/myservice").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[0]}/myservice").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[1]}/myservice").returns true
provider.initscript.should == "/alt/service/path/myservice"
end
it "should be able to find the init script if it ends with .sh" do
- File.expects(:exist?).with("#{paths[0]}/myservice").returns false
- File.expects(:exist?).with("#{paths[1]}/myservice").returns false
- File.expects(:exist?).with("#{paths[0]}/myservice.sh").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[0]}/myservice").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[1]}/myservice").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("#{paths[0]}/myservice.sh").returns true
provider.initscript.should == "/service/path/myservice.sh"
end
it "should fail if the service isn't there" do
paths.each do |path|
- File.expects(:exist?).with("#{path}/myservice").returns false
- File.expects(:exist?).with("#{path}/myservice.sh").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("#{path}/myservice").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("#{path}/myservice.sh").returns false
end
expect { provider.initscript }.to raise_error(Puppet::Error, "Could not find init script for 'myservice'")
end
@@ -134,7 +134,7 @@ describe Puppet::Type.type(:service).provider(:init) do
before :each do
File.stubs(:directory?).with("/service/path").returns true
File.stubs(:directory?).with("/alt/service/path").returns true
- File.stubs(:exist?).with("/service/path/myservice").returns true
+ Puppet::FileSystem::File.stubs(:exist?).with("/service/path/myservice").returns true
end
[:start, :stop, :status, :restart].each do |method|
diff --git a/spec/unit/provider/service/launchd_spec.rb b/spec/unit/provider/service/launchd_spec.rb
index fc82fdd00..b126fb22d 100755
--- a/spec/unit/provider/service/launchd_spec.rb
+++ b/spec/unit/provider/service/launchd_spec.rb
@@ -209,29 +209,82 @@ describe Puppet::Type.type(:service).provider(:launchd) do
end
end
- describe "when encountering malformed plists" do
- let(:plist_without_label) do
- {
- 'LimitLoadToSessionType' => 'Aqua'
- }
- end
- let(:busted_plist_path) { '/Library/LaunchAgents/org.busted.plist' }
-
- it "[17624] should warn that the plist in question is being skipped" do
- provider.expects(:launchd_paths).returns(['/Library/LaunchAgents'])
- provider.expects(:return_globbed_list_of_file_paths).with('/Library/LaunchAgents').returns([busted_plist_path])
- provider.expects(:read_plist).with(busted_plist_path).returns(plist_without_label)
- Puppet.expects(:warning).with("The #{busted_plist_path} plist does not contain a 'label' key; Puppet is skipping it")
- provider.jobsearch
- end
-
- it "[15929] should skip plists that plutil cannot read" do
- provider.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout',
- busted_plist_path).raises(Puppet::ExecutionFailure, 'boom')
- Puppet.expects(:warning).with("Cannot read file #{busted_plist_path}; " +
- "Puppet is skipping it. \n" +
- "Details: boom")
- provider.read_plist(busted_plist_path)
+ describe "make_label_to_path_map" do
+ before do
+ # clear out this class variable between runs
+ if provider.instance_variable_defined? :@label_to_path_map
+ provider.send(:remove_instance_variable, :@label_to_path_map)
+ end
+ end
+ describe "when encountering malformed plists" do
+ let(:plist_without_label) do
+ {
+ 'LimitLoadToSessionType' => 'Aqua'
+ }
+ end
+ let(:busted_plist_path) { '/Library/LaunchAgents/org.busted.plist' }
+
+ it "[17624] should warn that the plist in question is being skipped" do
+ provider.expects(:launchd_paths).returns(['/Library/LaunchAgents'])
+ provider.expects(:return_globbed_list_of_file_paths).with('/Library/LaunchAgents').returns([busted_plist_path])
+ provider.expects(:read_plist).with(busted_plist_path).returns(plist_without_label)
+ Puppet.expects(:warning).with("The #{busted_plist_path} plist does not contain a 'label' key; Puppet is skipping it")
+ provider.make_label_to_path_map
+ end
+
+ it "[15929] should skip plists that plutil cannot read" do
+ provider.expects(:plutil).with('-convert', 'xml1', '-o', '/dev/stdout',
+ busted_plist_path).raises(Puppet::ExecutionFailure, 'boom')
+ Puppet.expects(:warning).with("Cannot read file #{busted_plist_path}; " +
+ "Puppet is skipping it. \n" +
+ "Details: boom")
+ provider.read_plist(busted_plist_path)
+ end
+ end
+ it "should return the cached value when available" do
+ provider.instance_variable_set(:@label_to_path_map, {'xx'=>'yy'})
+ provider.make_label_to_path_map.should eq({'xx'=>'yy'})
+ end
+ describe "when successful" do
+ let(:launchd_dir) { '/Library/LaunchAgents' }
+ let(:plist) { launchd_dir + '/foo.bar.service.plist' }
+ let(:label) { 'foo.bar.service' }
+ before do
+ provider.instance_variable_set(:@label_to_path_map, nil)
+ provider.expects(:launchd_paths).returns([launchd_dir])
+ provider.expects(:return_globbed_list_of_file_paths).with(launchd_dir).returns([plist])
+ provider.expects(:read_plist).with(plist).returns({'Label'=>'foo.bar.service'})
+ end
+ it "should read the plists and return their contents" do
+ provider.make_label_to_path_map.should eq({label=>plist})
+ end
+ it "should re-read the plists and return their contents when refreshed" do
+ provider.instance_variable_set(:@label_to_path_map, {'xx'=>'yy'})
+ provider.make_label_to_path_map(true).should eq({label=>plist})
+ end
+ end
+ end
+
+ describe "jobsearch" do
+ let(:map) { {"org.mozilla.puppet" => "/path/to/puppet.plist",
+ "org.mozilla.python" => "/path/to/python.plist"} }
+ it "returns the entire map with no args" do
+ provider.expects(:make_label_to_path_map).returns(map)
+ provider.jobsearch.should == map
+ end
+ it "returns a singleton hash when given a label" do
+ provider.expects(:make_label_to_path_map).returns(map)
+ provider.jobsearch("org.mozilla.puppet").should == { "org.mozilla.puppet" => "/path/to/puppet.plist" }
+ end
+ it "refreshes the label_to_path_map when label is not found" do
+ provider.expects(:make_label_to_path_map).with().returns({})
+ provider.expects(:make_label_to_path_map).with(true).returns(map)
+ provider.jobsearch("org.mozilla.puppet").should == { "org.mozilla.puppet" => "/path/to/puppet.plist" }
+ end
+ it "raises Puppet::Error when the label is still not found" do
+ provider.expects(:make_label_to_path_map).with().returns(map)
+ provider.expects(:make_label_to_path_map).with(true).returns(map)
+ expect { provider.jobsearch("NOSUCH") }.to raise_error(Puppet::Error)
end
end
end
diff --git a/spec/unit/provider/service/openbsd_spec.rb b/spec/unit/provider/service/openbsd_spec.rb
new file mode 100644
index 000000000..8c417986d
--- /dev/null
+++ b/spec/unit/provider/service/openbsd_spec.rb
@@ -0,0 +1,125 @@
+#!/usr/bin/env ruby
+#
+# Unit testing for the OpenBSD service provider
+
+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:service).provider(:openbsd)
+
+describe provider_class do
+ before :each do
+ Puppet::Type.type(:service).stubs(:defaultprovider).returns described_class
+ Facter.stubs(:value).with(:operatingsystem).returns :openbsd
+ end
+
+ let :rcscripts do
+ [
+ 'apmd',
+ 'aucat',
+ 'cron',
+ 'puppetd'
+ ]
+ end
+
+ describe "#instances" do
+ it "should have an instances method" do
+ described_class.should respond_to :instances
+ end
+
+ it "should list all available services" do
+ FileTest.expects(:directory?).with('/etc/rc.d').returns true
+ Dir.expects(:entries).with('/etc/rc.d').returns rcscripts
+
+ rcscripts.each do |script|
+ FileTest.expects(:executable?).with("/etc/rc.d/#{script}").returns true
+ end
+
+ described_class.instances.map(&:name).should == [
+ 'apmd',
+ 'aucat',
+ 'cron',
+ 'puppetd'
+ ]
+ end
+ end
+
+ describe "#start" do
+ it "should use the supplied start command if specified" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :start => '/bin/foo'))
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.start
+ end
+
+ it "should start the service otherwise" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', '-f', :start], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.expects(:search).with('sshd').returns('/etc/rc.d/sshd')
+ provider.start
+ end
+ end
+
+ describe "#stop" do
+ it "should use the supplied stop command if specified" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :stop => '/bin/foo'))
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.stop
+ end
+
+ it "should stop the service otherwise" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', :stop], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.expects(:search).with('sshd').returns('/etc/rc.d/sshd')
+ provider.stop
+ end
+ end
+
+ describe "#status" do
+ it "should use the status command from the resource" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', :status], :failonfail => false, :override_locale => false, :squelch => true).never
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true)
+ provider.status
+ end
+
+ it "should return :stopped when status command returns with a non-zero exitcode" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', :status], :failonfail => false, :override_locale => false, :squelch => true).never
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true)
+ $CHILD_STATUS.stubs(:exitstatus).returns 3
+ provider.status.should == :stopped
+ end
+
+ it "should return :running when status command returns with a zero exitcode" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', :status], :failonfail => false, :override_locale => false, :squelch => true).never
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => true)
+ $CHILD_STATUS.stubs(:exitstatus).returns 0
+ provider.status.should == :running
+ end
+ end
+
+ describe "#restart" do
+ it "should use the supplied restart command if specified" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :restart => '/bin/foo'))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', '-f', :restart], :failonfail => true, :override_locale => false, :squelch => true).never
+ provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.restart
+ end
+
+ it "should restart the service with rc-service restart if hasrestart is true" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => true))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', '-f', :restart], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.expects(:search).with('sshd').returns('/etc/rc.d/sshd')
+ provider.restart
+ end
+
+ it "should restart the service with rc-service stop/start if hasrestart is false" do
+ provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => false))
+ provider.expects(:execute).with(['/etc/rc.d/sshd', '-f', :restart], :failonfail => true, :override_locale => false, :squelch => true).never
+ provider.expects(:execute).with(['/etc/rc.d/sshd', :stop], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.expects(:execute).with(['/etc/rc.d/sshd', '-f', :start], :failonfail => true, :override_locale => false, :squelch => true)
+ provider.expects(:search).with('sshd').returns('/etc/rc.d/sshd')
+ provider.restart
+ end
+ end
+end
diff --git a/spec/unit/provider/service/openwrt_spec.rb b/spec/unit/provider/service/openwrt_spec.rb
index bc8a6323d..2113aceb4 100755
--- a/spec/unit/provider/service/openwrt_spec.rb
+++ b/spec/unit/provider/service/openwrt_spec.rb
@@ -33,7 +33,7 @@ describe Puppet::Type.type(:service).provider(:openwrt), :as_platform => :posix
# All OpenWrt tests operate on the init script directly. It must exist.
File.stubs(:directory?).with('/etc/init.d').returns true
- File.stubs(:exist?).with('/etc/init.d/myservice').returns true
+ Puppet::FileSystem::File.stubs(:exist?).with('/etc/init.d/myservice').returns true
FileTest.stubs(:file?).with('/etc/init.d/myservice').returns true
FileTest.stubs(:executable?).with('/etc/init.d/myservice').returns true
end
diff --git a/spec/unit/provider/service/runit_spec.rb b/spec/unit/provider/service/runit_spec.rb
index 5c5b37b37..cbdc19ba6 100755
--- a/spec/unit/provider/service/runit_spec.rb
+++ b/spec/unit/provider/service/runit_spec.rb
@@ -96,18 +96,25 @@ describe provider_class do
end
describe "when enabling" do
- it "should create a symlink between daemon dir and service dir" do
- FileTest.stubs(:symlink?).returns(false)
- File.expects(:symlink).with(File.join(@daemondir,"myservice"), File.join(@servicedir,"myservice")).returns(0)
+ it "should create a symlink between daemon dir and service dir", :if => Puppet.features.manages_symlinks? do
+ daemon_path = File.join(@daemondir,"myservice")
+ mock_daemon = mock(daemon_path)
+ Puppet::FileSystem::File.expects(:new).with(daemon_path).returns(mock_daemon)
+ service_path = File.join(@servicedir,"myservice")
+ mock_service = mock(service_path, :symlink? => false)
+ Puppet::FileSystem::File.expects(:new).with(service_path).returns(mock_service)
+ mock_daemon.expects(:symlink).with(File.join(@servicedir,"myservice")).returns(0)
@provider.enable
end
end
describe "when disabling" do
it "should remove the '/etc/service/myservice' symlink" do
+ path = File.join(@servicedir,"myservice")
+ mocked_file = mock(path, :symlink? => true)
FileTest.stubs(:directory?).returns(false)
- FileTest.stubs(:symlink?).returns(true)
- File.expects(:unlink).with(File.join(@servicedir,"myservice")).returns(0)
+ Puppet::FileSystem::File.expects(:new).with(path).returns(mocked_file)
+ Puppet::FileSystem::File.expects(:unlink).with(path).returns(0)
@provider.disable
end
end
diff --git a/spec/unit/provider/service/upstart_spec.rb b/spec/unit/provider/service/upstart_spec.rb
index e24857901..ed93386b3 100755
--- a/spec/unit/provider/service/upstart_spec.rb
+++ b/spec/unit/provider/service/upstart_spec.rb
@@ -51,8 +51,8 @@ describe Puppet::Type.type(:service).provider(:upstart) do
describe "#search" do
it "searches through paths to find a matching conf file" do
File.stubs(:directory?).returns(true)
- File.stubs(:exists?).returns(false)
- File.expects(:exists?).with("/etc/init/foo-bar.conf").returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with("/etc/init/foo-bar.conf").returns(true)
resource = Puppet::Type.type(:service).new(:name => "foo-bar", :provider => :upstart)
provider = provider_class.new(resource)
@@ -61,8 +61,8 @@ describe Puppet::Type.type(:service).provider(:upstart) do
it "searches for just the name of a compound named service" do
File.stubs(:directory?).returns(true)
- File.stubs(:exists?).returns(false)
- File.expects(:exists?).with("/etc/init/network-interface.conf").returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with("/etc/init/network-interface.conf").returns(true)
resource = Puppet::Type.type(:service).new(:name => "network-interface INTERFACE=lo", :provider => :upstart)
provider = provider_class.new(resource)
diff --git a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
index 5cfa8994b..4d17ffe51 100755
--- a/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
+++ b/spec/unit/provider/ssh_authorized_key/parsed_spec.rb
@@ -162,7 +162,7 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
end
it "should create the directory" do
- File.stubs(:exist?).with("/tmp/.ssh_dir").returns false
+ Puppet::FileSystem::File.stubs(:exist?).with("/tmp/.ssh_dir").returns false
Dir.expects(:mkdir).with("/tmp/.ssh_dir", 0700)
@provider.flush
end
@@ -199,19 +199,19 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
end
it "should create the directory if it doesn't exist" do
- File.stubs(:exist?).with(@dir).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@dir).returns false
Dir.expects(:mkdir).with(@dir,0700)
@provider.flush
end
it "should not create or chown the directory if it already exist" do
- File.stubs(:exist?).with(@dir).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@dir).returns false
Dir.expects(:mkdir).never
@provider.flush
end
it "should absolutely not chown the directory to the user if it creates it" do
- File.stubs(:exist?).with(@dir).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@dir).returns false
Dir.stubs(:mkdir).with(@dir,0700)
uid = Puppet::Util.uid("nobody")
File.expects(:chown).never
@@ -219,7 +219,7 @@ describe provider_class, :unless => Puppet.features.microsoft_windows? do
end
it "should not create or chown the directory if it already exist" do
- File.stubs(:exist?).with(@dir).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@dir).returns false
Dir.expects(:mkdir).never
File.expects(:chown).never
@provider.flush
diff --git a/spec/unit/provider/user/directoryservice_spec.rb b/spec/unit/provider/user/directoryservice_spec.rb
index e464e2c6f..fe72bfc4f 100755
--- a/spec/unit/provider/user/directoryservice_spec.rb
+++ b/spec/unit/provider/user/directoryservice_spec.rb
@@ -704,7 +704,7 @@ describe Puppet::Type.type(:user).provider(:directoryservice) do
let(:stub_password_file) { stub('connection') }
it 'should return a sha1 hash read from disk' do
- File.expects(:exists?).with(password_hash_file).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(password_hash_file).returns(true)
File.expects(:file?).with(password_hash_file).returns(true)
File.expects(:readable?).with(password_hash_file).returns(true)
File.expects(:new).with(password_hash_file).returns(stub_password_file)
@@ -714,18 +714,18 @@ describe Puppet::Type.type(:user).provider(:directoryservice) do
end
it 'should return nil if the password_hash_file does not exist' do
- File.expects(:exists?).with(password_hash_file).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with(password_hash_file).returns(false)
provider.class.get_sha1('user_guid').should == nil
end
it 'should return nil if the password_hash_file is not a file' do
- File.expects(:exists?).with(password_hash_file).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(password_hash_file).returns(true)
File.expects(:file?).with(password_hash_file).returns(false)
provider.class.get_sha1('user_guid').should == nil
end
it 'should raise an error if the password_hash_file is not readable' do
- File.expects(:exists?).with(password_hash_file).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(password_hash_file).returns(true)
File.expects(:file?).with(password_hash_file).returns(true)
File.expects(:readable?).with(password_hash_file).returns(false)
expect { provider.class.get_sha1('user_guid').should == nil }.to raise_error Puppet::Error, /Could not read password hash file at #{password_hash_file}/
diff --git a/spec/unit/provider/user/windows_adsi_spec.rb b/spec/unit/provider/user/windows_adsi_spec.rb
index 4e3a6f463..c25ccaf95 100755
--- a/spec/unit/provider/user/windows_adsi_spec.rb
+++ b/spec/unit/provider/user/windows_adsi_spec.rb
@@ -24,7 +24,7 @@ describe Puppet::Type.type(:user).provider(:windows_adsi) do
it "should enumerate all users" do
names = ['user1', 'user2', 'user3']
stub_users = names.map{|n| stub(:name => n)}
- connection.stubs(:execquery).with("select name from win32_useraccount").returns(stub_users)
+ connection.stubs(:execquery).with('select name from win32_useraccount where localaccount = "TRUE"').returns(stub_users)
described_class.instances.map(&:name).should =~ names
end
diff --git a/spec/unit/provider/zone/solaris_spec.rb b/spec/unit/provider/zone/solaris_spec.rb
index 6fd58a46a..c143cabd1 100755
--- a/spec/unit/provider/zone/solaris_spec.rb
+++ b/spec/unit/provider/zone/solaris_spec.rb
@@ -138,7 +138,7 @@ net:
it "should not require path if sysidcfg is specified" do
resource[:path] = '/mypath'
resource[:sysidcfg] = 'dummy'
- File.stubs(:exists?).with('/mypath/root/etc/sysidcfg').returns true
+ Puppet::FileSystem::File.stubs(:exist?).with('/mypath/root/etc/sysidcfg').returns true
File.stubs(:directory?).with('/mypath/root/etc').returns true
provider.expects(:zoneadm).with(:boot)
provider.start
diff --git a/spec/unit/provider_spec.rb b/spec/unit/provider_spec.rb
index 208094b7e..31e69f799 100755
--- a/spec/unit/provider_spec.rb
+++ b/spec/unit/provider_spec.rb
@@ -349,10 +349,10 @@ describe Puppet::Provider do
command = Puppet::Util.which('sh') || Puppet::Util.which('cmd.exe')
parent.commands :sh => command
- FileTest.should be_exists parent.command(:sh)
+ Puppet::FileSystem::File.exist?(parent.command(:sh)).should be_true
parent.command(:sh).should =~ /#{Regexp.escape(command)}$/
- FileTest.should be_exists child.command(:sh)
+ Puppet::FileSystem::File.exist?(child.command(:sh)).should be_true
child.command(:sh).should =~ /#{Regexp.escape(command)}$/
end
diff --git a/spec/unit/reports/http_spec.rb b/spec/unit/reports/http_spec.rb
index 13f202607..1a99761d8 100755
--- a/spec/unit/reports/http_spec.rb
+++ b/spec/unit/reports/http_spec.rb
@@ -15,65 +15,50 @@ describe processor do
http.expects(:post).returns(httpok)
end
- it "should use the reporturl setting's host, port and ssl option" do
- uri = URI.parse(Puppet[:reporturl])
- ssl = (uri.scheme == 'https')
- Net::HTTP.expects(:new).with(
- uri.host, uri.port, optionally(anything, anything)
- ).returns http
- http.expects(:use_ssl=).with(ssl)
- subject.process
- end
+ it "configures the connection for ssl when using https" do
+ Puppet[:reporturl] = 'https://testing:8080/the/path'
- it "uses ssl if reporturl has the https protocol" do
- Puppet[:reporturl] = "https://myhost.mydomain:1234/report/upload"
- uri = URI.parse(Puppet[:reporturl])
- Net::HTTP.expects(:new).with(
- uri.host, uri.port, optionally(anything, anything)
+ Puppet::Network::HttpPool.expects(:http_instance).with(
+ 'testing', 8080, true
).returns http
- http.expects(:use_ssl=).with(true)
+
subject.process
end
- it "does not use ssl if reporturl has plain http protocol" do
- Puppet[:reporturl] = "http://myhost.mydomain:1234/report/upload"
- uri = URI.parse(Puppet[:reporturl])
- Net::HTTP.expects(:new).with(
- uri.host, uri.port, optionally(anything, anything)
+ it "does not configure the connectino for ssl when using http" do
+ Puppet[:reporturl] = "http://testing:8080/the/path"
+
+ Puppet::Network::HttpPool.expects(:http_instance).with(
+ 'testing', 8080, false
).returns http
- http.expects(:use_ssl=).with(false)
+
subject.process
end
end
describe "when making a request" do
- let(:http) { stub_everything "http" }
+ let(:connection) { stub_everything "connection" }
let(:httpok) { Net::HTTPOK.new('1.1', 200, '') }
before :each do
- Net::HTTP.expects(:new).returns(http)
+ Puppet::Network::HttpPool.expects(:http_instance).returns(connection)
end
it "should use the path specified by the 'reporturl' setting" do
- http.expects(:post).with {|path, data, headers|
- path.should == URI.parse(Puppet[:reporturl]).path
- }.returns(httpok)
+ report_path = URI.parse(Puppet[:reporturl]).path
+ connection.expects(:post).with(report_path, anything, anything).returns(httpok)
subject.process
end
it "should give the body as the report as YAML" do
- http.expects(:post).with {|path, data, headers|
- data.should == subject.to_yaml
- }.returns(httpok)
+ connection.expects(:post).with(anything, subject.to_yaml, anything).returns(httpok)
subject.process
end
it "should set content-type to 'application/x-yaml'" do
- http.expects(:post).with {|path, data, headers|
- headers["Content-Type"].should == "application/x-yaml"
- }.returns(httpok)
+ connection.expects(:post).with(anything, anything, has_entry("Content-Type" => "application/x-yaml")).returns(httpok)
subject.process
end
@@ -82,7 +67,7 @@ describe processor do
if code.to_i >= 200 and code.to_i < 300
it "should succeed on http code #{code}" do
response = klass.new('1.1', code, '')
- http.expects(:post).returns(response)
+ connection.expects(:post).returns(response)
Puppet.expects(:err).never
subject.process
@@ -92,7 +77,7 @@ describe processor do
if code.to_i >= 300 && ![301, 302, 307].include?(code.to_i)
it "should log error on http code #{code}" do
response = klass.new('1.1', code, '')
- http.expects(:post).returns(response)
+ connection.expects(:post).returns(response)
Puppet.expects(:err)
subject.process
diff --git a/spec/unit/reports/store_spec.rb b/spec/unit/reports/store_spec.rb
index 5320c6479..421f8404d 100755
--- a/spec/unit/reports/store_spec.rb
+++ b/spec/unit/reports/store_spec.rb
@@ -47,7 +47,7 @@ describe processor do
it "rejects invalid hostnames" do
@report.host = ".."
- FileTest.expects(:exists?).never
+ Puppet::FileSystem::File.expects(:exist?).never
Tempfile.expects(:new).never
expect { @report.process }.to raise_error(ArgumentError, /Invalid node/)
end
@@ -55,7 +55,7 @@ describe processor do
describe "::destroy" do
it "rejects invalid hostnames" do
- File.expects(:unlink).never
+ Puppet::FileSystem::File.expects(:unlink).never
expect { processor.destroy("..") }.to raise_error(ArgumentError, /Invalid node/)
end
end
diff --git a/spec/unit/resource/catalog_spec.rb b/spec/unit/resource/catalog_spec.rb
index dab6e4591..dd88e8e20 100755
--- a/spec/unit/resource/catalog_spec.rb
+++ b/spec/unit/resource/catalog_spec.rb
@@ -1,5 +1,18 @@
#! /usr/bin/env ruby
require 'spec_helper'
+require 'puppet_spec/compiler'
+
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ CATALOG_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__), '../../../api/schemas/catalog.json')))
+
+ describe "catalog schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, CATALOG_SCHEMA)
+ end
+ end
+
+end
describe Puppet::Resource::Catalog, "when compiling" do
include PuppetSpec::Files
@@ -86,26 +99,28 @@ describe Puppet::Resource::Catalog, "when compiling" do
it "should accept tags" do
config = Puppet::Resource::Catalog.new("mynode")
config.tag("one")
- config.tags.should == %w{one}
+ config.should be_tagged("one")
end
it "should accept multiple tags at once" do
config = Puppet::Resource::Catalog.new("mynode")
config.tag("one", "two")
- config.tags.should == %w{one two}
+ config.should be_tagged("one")
+ config.should be_tagged("two")
end
it "should convert all tags to strings" do
config = Puppet::Resource::Catalog.new("mynode")
config.tag("one", :two)
- config.tags.should == %w{one two}
+ config.should be_tagged("one")
+ config.should be_tagged("two")
end
it "should tag with both the qualified name and the split name" do
config = Puppet::Resource::Catalog.new("mynode")
config.tag("one::two")
- config.tags.include?("one").should be_true
- config.tags.include?("one::two").should be_true
+ config.should be_tagged("one")
+ config.should be_tagged("one::two")
end
it "should accept classes" do
@@ -119,7 +134,7 @@ describe Puppet::Resource::Catalog, "when compiling" do
it "should tag itself with passed class names" do
config = Puppet::Resource::Catalog.new("mynode")
config.add_class("one")
- config.tags.should == %w{one}
+ config.should be_tagged("one")
end
end
@@ -204,12 +219,12 @@ describe Puppet::Resource::Catalog, "when compiling" do
@r1 = stub_everything 'r1', :ref => "File[/a]"
@r1.stubs(:respond_to?).with(:ref).returns(true)
- @r1.stubs(:dup).returns(@r1)
+ @r1.stubs(:copy_as_resource).returns(@r1)
@r1.stubs(:is_a?).with(Puppet::Resource).returns(true)
@r2 = stub_everything 'r2', :ref => "File[/b]"
@r2.stubs(:respond_to?).with(:ref).returns(true)
- @r2.stubs(:dup).returns(@r2)
+ @r2.stubs(:copy_as_resource).returns(@r2)
@r2.stubs(:is_a?).with(Puppet::Resource).returns(true)
@resources = [@r1,@r2]
@@ -720,6 +735,60 @@ describe Puppet::Resource::Catalog, "when compiling" do
end
end
+describe Puppet::Resource::Catalog, "when converting a resource catalog to pson" do
+ include PuppetSpec::Compiler
+
+ def validate_json_for_catalog(catalog)
+ JSON::Validator.validate!(CATALOG_SCHEMA, catalog.to_pson)
+ end
+
+ it "should validate an empty catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ empty_catalog = compile_to_catalog("")
+ validate_json_for_catalog(empty_catalog)
+ end
+
+ it "should validate a noop catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ noop_catalog = compile_to_catalog("create_resources('file', {})")
+ validate_json_for_catalog(noop_catalog)
+ end
+
+ it "should validate a single resource catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ catalog = compile_to_catalog("create_resources('file', {'/etc/foo'=>{'ensure'=>'present'}})")
+ validate_json_for_catalog(catalog)
+ end
+
+ it "should validate a virtual resource catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ catalog = compile_to_catalog("create_resources('@file', {'/etc/foo'=>{'ensure'=>'present'}})\nrealize(File['/etc/foo'])")
+ validate_json_for_catalog(catalog)
+ end
+
+ it "should validate a single exported resource catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ catalog = compile_to_catalog("create_resources('@@file', {'/etc/foo'=>{'ensure'=>'present'}})")
+ validate_json_for_catalog(catalog)
+ end
+
+ it "should validate a two resource catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ catalog = compile_to_catalog("create_resources('notify', {'foo'=>{'message'=>'one'}, 'bar'=>{'message'=>'two'}})")
+ validate_json_for_catalog(catalog)
+ end
+
+ it "should validate a two parameter class catalog against the schema", :unless => Puppet.features.microsoft_windows? do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ class multi_param_class ($one, $two) {
+ notify {'foo':
+ message => "One is $one, two is $two",
+ }
+ }
+
+ class {'multi_param_class':
+ one => 'hello',
+ two => 'world',
+ }
+ MANIFEST
+ validate_json_for_catalog(catalog)
+ end
+end
+
describe Puppet::Resource::Catalog, "when converting to pson" do
before do
@catalog = Puppet::Resource::Catalog.new("myhost")
@@ -742,11 +811,11 @@ describe Puppet::Resource::Catalog, "when converting to pson" do
PSON.parse @catalog.to_pson
end
- [:name, :version, :tags, :classes].each do |param|
+ [:name, :version, :classes].each do |param|
it "should set its #{param} to the #{param} of the resource" do
@catalog.send(param.to_s + "=", "testing") unless @catalog.send(param)
- pson_output_should { |hash| hash['data'][param.to_s] == @catalog.send(param) }
+ pson_output_should { |hash| hash['data'][param.to_s].should == @catalog.send(param) }
PSON.parse @catalog.to_pson
end
end
@@ -815,7 +884,8 @@ describe Puppet::Resource::Catalog, "when converting from pson" do
it "should set any provided tags on the catalog" do
@data['tags'] = %w{one two}
PSON.parse @pson.to_pson
- @catalog.tags.should == @data['tags']
+ @catalog.should be_tagged("one")
+ @catalog.should be_tagged("two")
end
it "should set any provided classes on the catalog" do
diff --git a/spec/unit/resource/resource_type.json b/spec/unit/resource/resource_type.json
deleted file mode 100644
index ffd15d639..000000000
--- a/spec/unit/resource/resource_type.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "type": "object",
- "properties": {
- "doc": {
- "type": "string"
- },
- "line": {
- "type": "integer"
- },
- "file": {
- "type": "string"
- },
- "parent": {
- "type": "string"
- },
- "name": {
- "type": "string",
- "required": "true"
- },
- "kind": {
- "type": "string",
- "enum": [
- "class",
- "node",
- "defined_type"
- ],
- "required": "true"
- },
- "parameters": {
- "type": "object"
- }
- },
- "additionalProperties": false
-}
diff --git a/spec/unit/resource/status_spec.rb b/spec/unit/resource/status_spec.rb
index f3cc5699c..d50abdce3 100755
--- a/spec/unit/resource/status_spec.rb
+++ b/spec/unit/resource/status_spec.rb
@@ -59,7 +59,9 @@ describe Puppet::Resource::Status do
it "should copy the resource's tags" do
@resource.expects(:tags).returns %w{foo bar}
- Puppet::Resource::Status.new(@resource).tags.should == %w{foo bar}
+ status = Puppet::Resource::Status.new(@resource)
+ status.should be_tagged("foo")
+ status.should be_tagged("bar")
end
it "should always convert the resource to a string" do
@@ -113,6 +115,14 @@ describe Puppet::Resource::Status do
@status.events.should == [event]
end
+ it "records an event for a failure caused by an error" do
+ @status.failed_because(StandardError.new("the message"))
+
+ expect(@status.events[0].message).to eq("the message")
+ expect(@status.events[0].status).to eq("failure")
+ expect(@status.events[0].name).to eq(:resource_error)
+ end
+
it "should count the number of successful events and set changed" do
3.times{ @status << Puppet::Transaction::Event.new(:status => 'success') }
@status.change_count.should == 3
diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb
index a4929208e..1b5a4727b 100755
--- a/spec/unit/resource/type_spec.rb
+++ b/spec/unit/resource/type_spec.rb
@@ -1,8 +1,19 @@
#! /usr/bin/env ruby
require 'spec_helper'
-
require 'puppet/resource/type'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ RESOURCE_TYPE_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__), '../../../api/schemas/resource_type.json')))
+
+ describe "resource type schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, RESOURCE_TYPE_SCHEMA)
+ end
+ end
+
+end
+
describe Puppet::Resource::Type do
it "should have a 'name' attribute" do
Puppet::Resource::Type.new(:hostclass, "foo").name.should == "foo"
@@ -31,6 +42,10 @@ describe Puppet::Resource::Type do
end
describe "when converting to json" do
+ def validate_json_for_type(type)
+ JSON::Validator.validate!(RESOURCE_TYPE_SCHEMA, type.to_pson)
+ end
+
before do
@type = Puppet::Resource::Type.new(:hostclass, "foo")
end
@@ -48,6 +63,20 @@ describe Puppet::Resource::Type do
double_convert.type.should == @type.type
end
+ it "should validate with only name and kind", :unless => Puppet.features.microsoft_windows? do
+ validate_json_for_type(@type)
+ end
+
+ it "should validate with all fields set", :unless => Puppet.features.microsoft_windows? do
+ @type.set_arguments("one" => nil, "two" => "foo")
+ @type.line = 100
+ @type.doc = "A weird type"
+ @type.file = "/etc/manifests/thing.pp"
+ @type.parent = "one::two"
+
+ validate_json_for_type(@type)
+ end
+
it "should include any arguments" do
@type.set_arguments("one" => nil, "two" => "foo")
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 37d2001b8..a8f21d205 100755
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -339,8 +339,11 @@ describe Puppet::Resource do
end
it "should query the injector using a namespaced key" do
- compiler.injector.expects(:lookup).with(scope, 'apache::port')
+ compiler.injector.expects(:lookup).with(scope, 'apache::port').returns("8081")
+
resource.set_default_parameters(scope)
+
+ resource[:port].should == "8081"
end
it "should use the value from the data_binding terminus" do
@@ -376,8 +379,16 @@ describe Puppet::Resource do
resource[:port].should == '80'
end
+ it "should fail with error message about data binding on a hiera failure" do
+ Puppet::DataBinding.indirection.expects(:find).raises(Puppet::DataBinding::LookupError, 'Forgettabotit')
+ expect {
+ resource.set_default_parameters(scope)
+ }.to raise_error(Puppet::Error, /Error from DataBinding 'hiera' while looking up 'apache::port':.*Forgettabotit/)
+ end
+
it "should use the default value if the injector returns nil" do
compiler.injector.expects(:lookup).returns(nil)
+ Puppet::DataBinding.indirection.expects(:find).returns(nil)
resource.set_default_parameters(scope)
@@ -607,7 +618,7 @@ describe Puppet::Resource do
end
end
- describe "when serializing" do
+ describe "when serializing a native type" do
before do
@resource = Puppet::Resource.new("file", "/my/file")
@resource["one"] = "test"
@@ -622,6 +633,31 @@ describe Puppet::Resource do
end
end
+ describe "when serializing a defined type" do
+ before do
+ type = Puppet::Resource::Type.new(:definition, "foo::bar")
+ Puppet::Node::Environment.new.known_resource_types.add type
+ end
+
+ before :each do
+ @resource = Puppet::Resource.new('foo::bar', 'xyzzy')
+ @resource['one'] = 'test'
+ @resource['two'] = 'other'
+ @resource.resource_type
+ end
+
+ it "doesn't include transient instance variables (#4506)" do
+ expect(@resource.to_yaml_properties).to_not include :@rstype
+ end
+
+ it "produces an equivalent yaml object" do
+ text = @resource.render('yaml')
+
+ newresource = Puppet::Resource.convert_from('yaml', text)
+ newresource.should equal_attributes_of @resource
+ end
+ end
+
describe "when converting to a RAL resource" do
it "should use the resource type's :new method to create the resource if the resource is of a builtin type" do
resource = Puppet::Resource.new("file", basepath+"/my/file")
@@ -810,9 +846,9 @@ describe Puppet::Resource do
end
end
- describe "it should implement to_resource" do
+ describe "it should implement copy_as_resource" do
resource = Puppet::Resource.new("file", "/my/file")
- resource.to_resource.should == resource
+ resource.copy_as_resource.should == resource
end
describe "because it is an indirector model" do
diff --git a/spec/unit/settings/autosign_setting_spec.rb b/spec/unit/settings/autosign_setting_spec.rb
new file mode 100644
index 000000000..c08171374
--- /dev/null
+++ b/spec/unit/settings/autosign_setting_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+require 'puppet/settings'
+require 'puppet/settings/autosign_setting'
+
+describe Puppet::Settings::AutosignSetting do
+ let(:setting) { described_class.new(:settings => mock('settings'), :desc => "test") }
+
+ it "is of type :autosign" do
+ expect(setting.type).to eq :autosign
+ end
+
+ describe "when munging the setting" do
+ it "passes boolean values through" do
+ expect(setting.munge(true)).to eq true
+ expect(setting.munge(false)).to eq false
+ end
+
+ it "converts nil to false" do
+ expect(setting.munge(nil)).to eq false
+ end
+
+ it "munges string 'true' to boolean true" do
+ expect(setting.munge('true')).to eq true
+ end
+
+ it "munges string 'false' to boolean false" do
+ expect(setting.munge('false')).to eq false
+ end
+
+ it "passes absolute paths through" do
+ path = File.expand_path('/path/to/autosign.conf')
+ expect(setting.munge(path)).to eq path
+ end
+
+ it "fails if given anything else" do
+ cases = [1.0, 'sometimes', 'relative/autosign.conf']
+
+ cases.each do |invalid|
+ expect {
+ setting.munge(invalid)
+ }.to raise_error Puppet::Settings::ValidationError, /Invalid autosign value/
+ end
+ end
+ end
+end
diff --git a/spec/unit/settings/file_setting_spec.rb b/spec/unit/settings/file_setting_spec.rb
index a6e3f3f12..d9c6f5629 100755
--- a/spec/unit/settings/file_setting_spec.rb
+++ b/spec/unit/settings/file_setting_spec.rb
@@ -139,14 +139,14 @@ describe Puppet::Settings::FileSetting do
it "should skip non-existent files if 'create_files' is not enabled" do
@file.expects(:create_files?).returns false
@file.expects(:type).returns :file
- File.expects(:exist?).with(@basepath).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@basepath).returns false
@file.to_resource.should be_nil
end
it "should manage existent files even if 'create_files' is not enabled" do
@file.expects(:create_files?).returns false
@file.expects(:type).returns :file
- File.expects(:exist?).with(@basepath).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(@basepath).returns true
@file.to_resource.should be_instance_of(Puppet::Resource)
end
diff --git a/spec/unit/settings/path_setting_spec.rb b/spec/unit/settings/path_setting_spec.rb
index d2ec46b5d..b7bc3198c 100755
--- a/spec/unit/settings/path_setting_spec.rb
+++ b/spec/unit/settings/path_setting_spec.rb
@@ -22,8 +22,8 @@ describe Puppet::Settings::PathSetting do
end
it "should work with UNC paths" do
- subject.munge('//server/some/path').should == '//server/some/path'
- subject.munge('\\\\server\some\path').should == '//server/some/path'
+ subject.munge('//localhost/some/path').should == '//localhost/some/path'
+ subject.munge('\\\\localhost\some\path').should == '//localhost/some/path'
end
end
end
diff --git a/spec/unit/settings/priority_setting_spec.rb b/spec/unit/settings/priority_setting_spec.rb
new file mode 100755
index 000000000..d51e39dc4
--- /dev/null
+++ b/spec/unit/settings/priority_setting_spec.rb
@@ -0,0 +1,66 @@
+#!/usr/bin/env ruby
+require 'spec_helper'
+
+require 'puppet/settings'
+require 'puppet/settings/priority_setting'
+require 'puppet/util/platform'
+
+describe Puppet::Settings::PrioritySetting do
+ let(:setting) { described_class.new(:settings => mock('settings'), :desc => "test") }
+
+ it "is of type :priority" do
+ setting.type.should == :priority
+ end
+
+ describe "when munging the setting" do
+ it "passes nil through" do
+ setting.munge(nil).should be_nil
+ end
+
+ it "returns the same value if given an integer" do
+ setting.munge(5).should == 5
+ end
+
+ it "returns an integer if given a decimal string" do
+ setting.munge('12').should == 12
+ end
+
+ it "returns a negative integer if given a negative integer string" do
+ setting.munge('-5').should == -5
+ end
+
+ it "fails if given anything else" do
+ [ 'foo', 'realtime', true, 8.3, [] ].each do |value|
+ expect {
+ setting.munge(value)
+ }.to raise_error(Puppet::Settings::ValidationError)
+ end
+ end
+
+ describe "on a Unix-like platform it", :unless => Puppet::Util::Platform.windows? do
+ it "parses high, normal, low, and idle priorities" do
+ {
+ 'high' => -10,
+ 'normal' => 0,
+ 'low' => 10,
+ 'idle' => 19
+ }.each do |value, converted_value|
+ setting.munge(value).should == converted_value
+ end
+ end
+ end
+
+ describe "on a Windows-like platform it", :if => Puppet::Util::Platform.windows? do
+ it "parses high, normal, low, and idle priorities" do
+ {
+ 'high' => Process::HIGH_PRIORITY_CLASS,
+ 'normal' => Process::NORMAL_PRIORITY_CLASS,
+ 'low' => Process::BELOW_NORMAL_PRIORITY_CLASS,
+ 'idle' => Process::IDLE_PRIORITY_CLASS
+ }.each do |value, converted_value|
+ setting.munge(value).should == converted_value
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/settings_spec.rb b/spec/unit/settings_spec.rb
index 12107bcb7..b3dc31f3d 100755
--- a/spec/unit/settings_spec.rb
+++ b/spec/unit/settings_spec.rb
@@ -485,7 +485,7 @@ describe Puppet::Settings do
:three => { :default => "$one $two THREE", :desc => "c"},
:four => { :default => "$two $three FOUR", :desc => "d"},
:five => { :default => nil, :desc => "e" }
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
end
describe "call_on_define" do
@@ -589,7 +589,7 @@ describe Puppet::Settings do
:config => { :type => :file, :default => "/my/file", :desc => "a" },
:one => { :default => "ONE", :desc => "a" },
:two => { :default => "TWO", :desc => "b" }
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
@settings.preferred_run_mode = :agent
end
@@ -666,8 +666,8 @@ describe Puppet::Settings do
describe "when root" do
it "should look for the main config file default location config settings haven't been overridden'" do
Puppet.features.stubs(:root?).returns(true)
- FileTest.expects(:exist?).with(main_config_file_default_location).returns(false)
- FileTest.expects(:exist?).with(user_config_file_default_location).never
+ Puppet::FileSystem::File.expects(:exist?).with(main_config_file_default_location).returns(false)
+ Puppet::FileSystem::File.expects(:exist?).with(user_config_file_default_location).never
@settings.send(:parse_config_files)
end
@@ -678,7 +678,7 @@ describe Puppet::Settings do
Puppet.features.stubs(:root?).returns(false)
seq = sequence "load config files"
- FileTest.expects(:exist?).with(user_config_file_default_location).returns(false).in_sequence(seq)
+ Puppet::FileSystem::File.expects(:exist?).with(user_config_file_default_location).returns(false).in_sequence(seq)
@settings.send(:parse_config_files)
end
@@ -699,8 +699,8 @@ describe Puppet::Settings do
:two => { :default => "$one TWO", :desc => "b" },
:three => { :default => "$one $two THREE", :desc => "c" }
@settings.stubs(:user_config_file).returns(@userconfig)
- FileTest.stubs(:exist?).with(@file).returns true
- FileTest.stubs(:exist?).with(@userconfig).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@file).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@userconfig).returns false
end
it "should not ignore the report setting" do
@@ -712,7 +712,7 @@ describe Puppet::Settings do
[puppetd]
report=true
CONF
- FileTest.expects(:exist?).with(myfile).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(myfile).returns(true)
@settings.expects(:read_file).returns(text)
@settings.send(:parse_config_files)
@settings[:report].should be_true
@@ -722,7 +722,7 @@ describe Puppet::Settings do
myfile = make_absolute("/my/file") # do not stub expand_path here, as this leads to a stack overflow, when mocha tries to use it
@settings[:config] = myfile
- FileTest.expects(:exist?).with(myfile).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(myfile).returns(true)
File.expects(:read).with(myfile).returns "[main]"
@@ -730,7 +730,7 @@ describe Puppet::Settings do
end
it "should not try to parse non-existent files" do
- FileTest.expects(:exist?).with(@file).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@file).returns false
File.expects(:read).with(@file).never
@@ -881,6 +881,33 @@ describe Puppet::Settings do
values.should == ["yay/setval"]
end
+ it "should allow hooks invoked at parse time to be deferred" do
+ hook_invoked = false
+ @settings.define_settings :section, :deferred => {:desc => '',
+ :hook => proc { |v| hook_invoked = true },
+ :call_hook => :on_initialize_and_write, }
+
+ @settings.define_settings(:main,
+ :logdir => { :type => :directory, :default => nil, :desc => "logdir" },
+ :confdir => { :type => :directory, :default => nil, :desc => "confdir" },
+ :vardir => { :type => :directory, :default => nil, :desc => "vardir" })
+
+ text = <<-EOD
+ [main]
+ deferred=$confdir/goose
+ EOD
+
+ @settings.stubs(:read_file).returns(text)
+ @settings.initialize_global_settings
+
+ hook_invoked.should be_false
+
+ @settings.initialize_app_defaults(:logdir => '/path/to/logdir', :confdir => '/path/to/confdir', :vardir => '/path/to/vardir')
+
+ hook_invoked.should be_true
+ @settings[:deferred].should eq File.expand_path('/path/to/confdir/goose')
+ end
+
it "should allow empty values" do
@settings.define_settings :section, :myarg => { :default => "myfile", :desc => "a" }
@@ -925,7 +952,7 @@ describe Puppet::Settings do
context "running non-root without explicit config file" do
before :each do
Puppet.features.stubs(:root?).returns(false)
- FileTest.expects(:exist?).
+ Puppet::FileSystem::File.expects(:exist?).
with(user_config_file_default_location).
returns(true).in_sequence(seq)
@settings.expects(:read_file).
@@ -947,7 +974,7 @@ describe Puppet::Settings do
context "running as root without explicit config file" do
before :each do
Puppet.features.stubs(:root?).returns(true)
- FileTest.expects(:exist?).
+ Puppet::FileSystem::File.expects(:exist?).
with(main_config_file_default_location).
returns(true).in_sequence(seq)
@settings.expects(:read_file).
@@ -970,7 +997,7 @@ describe Puppet::Settings do
before :each do
Puppet.features.stubs(:root?).returns(false)
@settings[:confdir] = File.dirname(main_config_file_default_location)
- FileTest.expects(:exist?).
+ Puppet::FileSystem::File.expects(:exist?).
with(main_config_file_default_location).
returns(true).in_sequence(seq)
@settings.expects(:read_file).
@@ -1000,13 +1027,13 @@ describe Puppet::Settings do
:one => { :default => "ONE", :desc => "a" },
:two => { :default => "$one TWO", :desc => "b" },
:three => { :default => "$one $two THREE", :desc => "c" }
- FileTest.stubs(:exist?).with(@file).returns true
- FileTest.stubs(:exist?).with(@userconfig).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@file).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@userconfig).returns false
@settings.stubs(:user_config_file).returns(@userconfig)
end
it "does not create the WatchedFile instance and should not parse if the file does not exist" do
- FileTest.expects(:exist?).with(@file).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(@file).returns false
Puppet::Util::WatchedFile.expects(:new).never
@settings.expects(:parse_config_files).never
@@ -1285,10 +1312,6 @@ describe Puppet::Settings do
@settings.define_settings :files, :myfile => {:type => :file, :default => make_absolute("/myfile"), :desc => "a", :mode => 0755}
end
- it "should provide a method that writes files with the correct modes" do
- @settings.should respond_to(:write)
- end
-
it "should provide a method that creates directories with the correct modes" do
Puppet::Util::SUIDManager.expects(:asuser).with("suser", "sgroup").yields
Dir.expects(:mkdir).with(make_absolute("/otherdir"), 0755)
@@ -1567,17 +1590,6 @@ describe Puppet::Settings do
end
end
- describe "#writesub" do
- it "should only pass valid arguments to File.open" do
- settings = Puppet::Settings.new
- settings.stubs(:get_config_file_default).with(:privatekeydir).returns(OpenStruct.new(:mode => "750"))
-
- File.expects(:open).with("/path/to/keydir", "w", 750).returns true
- settings.writesub(:privatekeydir, "/path/to/keydir")
- end
- end
-
-
describe "when dealing with command-line options" do
let(:settings) { Puppet::Settings.new }
diff --git a/spec/unit/ssl/certificate_authority/autosign_command_spec.rb b/spec/unit/ssl/certificate_authority/autosign_command_spec.rb
new file mode 100644
index 000000000..5792bb4f5
--- /dev/null
+++ b/spec/unit/ssl/certificate_authority/autosign_command_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+require 'puppet/ssl/certificate_authority/autosign_command'
+
+describe Puppet::SSL::CertificateAuthority::AutosignCommand do
+
+ let(:csr) { stub 'csr', :name => 'host', :to_s => 'CSR PEM goes here' }
+ let(:decider) { Puppet::SSL::CertificateAuthority::AutosignCommand.new('/autosign/command') }
+
+ it "returns true if the command succeeded" do
+ executes_the_command_resulting_in(0)
+
+ decider.allowed?(csr).should == true
+ end
+
+ it "returns false if the command failed" do
+ executes_the_command_resulting_in(1)
+
+ decider.allowed?(csr).should == false
+ end
+
+ def executes_the_command_resulting_in(exitstatus)
+ Puppet::Util::Execution.expects(:execute).
+ with(['/autosign/command', 'host'],
+ has_entries(:stdinfile => anything,
+ :combine => true,
+ :failonfail => false)).
+ returns(Puppet::Util::Execution::ProcessOutput.new('', exitstatus))
+ end
+end
diff --git a/spec/unit/ssl/certificate_authority_spec.rb b/spec/unit/ssl/certificate_authority_spec.rb
index 70186a137..13c169a0a 100755
--- a/spec/unit/ssl/certificate_authority_spec.rb
+++ b/spec/unit/ssl/certificate_authority_spec.rb
@@ -92,12 +92,6 @@ describe Puppet::SSL::CertificateAuthority do
Puppet::SSL::CertificateAuthority.new
end
- it "should create an inventory instance" do
- Puppet::SSL::Inventory.expects(:new).returns "inventory"
-
- Puppet::SSL::CertificateAuthority.new.inventory.should == "inventory"
- end
-
it "should make sure the CA is set up" do
Puppet::SSL::CertificateAuthority.any_instance.expects(:setup)
@@ -171,16 +165,16 @@ describe Puppet::SSL::CertificateAuthority do
it "should create and store a password at :capass" do
Puppet[:capass] = File.expand_path("/path/to/pass")
- FileTest.expects(:exist?).with(Puppet[:capass]).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(Puppet[:capass]).returns false
- fh = mock 'filehandle'
- Puppet.settings.expects(:write).with(:capass).yields fh
-
- fh.expects(:print).with { |s| s.length > 18 }
+ fh = StringIO.new
+ Puppet.settings.setting(:capass).expects(:open).with('w').yields fh
@ca.stubs(:sign)
@ca.generate_ca_certificate
+
+ expect(fh.string.length).to be > 18
end
it "should generate a key if one does not exist" do
@@ -238,11 +232,10 @@ describe Puppet::SSL::CertificateAuthority do
Puppet::SSL::Certificate.stubs(:new).returns @cert
- @cert.stubs(:content=)
Puppet::SSL::Certificate.indirection.stubs(:save)
# Stub out the factory
- Puppet::SSL::CertificateFactory.stubs(:build).returns "my real cert"
+ Puppet::SSL::CertificateFactory.stubs(:build).returns @cert.content
@request_content = stub "request content stub", :subject => OpenSSL::X509::Name.new([['CN', @name]]), :public_key => stub('public_key')
@request = stub 'request', :name => @name, :request_extensions => [], :subject_alt_names => [], :content => @request_content
@@ -255,39 +248,6 @@ describe Puppet::SSL::CertificateAuthority do
Puppet::SSL::CertificateRequest.indirection.stubs(:destroy)
end
- describe "and calculating the next certificate serial number" do
- before do
- @path = File.expand_path("/path/to/serial")
- Puppet[:serial] = @path
-
- @filehandle = stub 'filehandle', :<< => @filehandle
- Puppet.settings.stubs(:readwritelock).with(:serial).yields @filehandle
- end
-
- it "should default to 0x1 for the first serial number" do
- @ca.next_serial.should == 0x1
- end
-
- it "should return the current content of the serial file" do
- FileTest.stubs(:exist?).with(@path).returns true
- File.expects(:read).with(@path).returns "0002"
-
- @ca.next_serial.should == 2
- end
-
- it "should write the next serial number to the serial file as hex" do
- @filehandle.expects(:<<).with("0002")
-
- @ca.next_serial
- end
-
- it "should lock the serial file while writing" do
- Puppet.settings.expects(:readwritelock).with(:serial)
-
- @ca.next_serial
- end
- end
-
describe "its own certificate" do
before do
@serial = 10
@@ -303,28 +263,28 @@ describe Puppet::SSL::CertificateAuthority do
it "should use a certificate type of :ca" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[0].should == :ca
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name, :ca, @request)
end
it "should pass the provided CSR as the CSR" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[1].should == @request
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name, :ca, @request)
end
it "should use the provided CSR's content as the issuer" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[2].subject.to_s.should == "/CN=myhost"
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name, :ca, @request)
end
it "should pass the next serial as the serial number" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[3].should == @serial
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name, :ca, @request)
end
@@ -355,7 +315,7 @@ describe Puppet::SSL::CertificateAuthority do
it "should use a certificate type of :server" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[0] == :server
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name)
end
@@ -404,14 +364,14 @@ describe Puppet::SSL::CertificateAuthority do
it "should use the CA certificate as the issuer" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[2] == @cacert.content
- end.returns "my real cert"
- @ca.sign(@name)
+ end.returns @cert.content
+ signed = @ca.sign(@name)
end
it "should pass the next serial as the serial number" do
Puppet::SSL::CertificateFactory.expects(:build).with do |*args|
args[3] == @serial
- end.returns "my real cert"
+ end.returns @cert.content
@ca.sign(@name)
end
@@ -518,6 +478,40 @@ describe Puppet::SSL::CertificateAuthority do
end
end
+ it "accepts numeric OIDs under the ppRegCertExt subtree" do
+ exts = [{ 'oid' => '1.3.6.1.4.1.34380.1.1.1',
+ 'value' => '657e4780-4cf5-11e3-8f96-0800200c9a66'}]
+
+ @request.stubs(:request_extensions).returns exts
+
+ expect {
+ @ca.check_internal_signing_policies(@name, @request, false)
+ }.to_not raise_error
+ end
+
+ it "accepts short name OIDs under the ppRegCertExt subtree" do
+ exts = [{ 'oid' => 'pp_uuid',
+ 'value' => '657e4780-4cf5-11e3-8f96-0800200c9a66'}]
+
+ @request.stubs(:request_extensions).returns exts
+
+ expect {
+ @ca.check_internal_signing_policies(@name, @request, false)
+ }.to_not raise_error
+ end
+
+ it "accepts OIDs under the ppPrivCertAttrs subtree" do
+ exts = [{ 'oid' => '1.3.6.1.4.1.34380.1.2.1',
+ 'value' => 'private extension'}]
+
+ @request.stubs(:request_extensions).returns exts
+
+ expect {
+ @ca.check_internal_signing_policies(@name, @request, false)
+ }.to_not raise_error
+ end
+
+
it "should reject a critical extension that isn't on the whitelist" do
@request.stubs(:request_extensions).returns [{ "oid" => "banana",
"value" => "yumm",
@@ -610,76 +604,104 @@ describe Puppet::SSL::CertificateAuthority do
end
describe "when autosigning certificates" do
- let(:autosign) { File.expand_path("/auto/sign") }
- it "should do nothing if autosign is disabled" do
- Puppet[:autosign] = 'false'
+ let(:csr) { Puppet::SSL::CertificateRequest.new("host") }
- Puppet::SSL::CertificateRequest.indirection.expects(:search).never
- @ca.autosign
- end
+ describe "using the autosign setting" do
+ let(:autosign) { File.expand_path("/auto/sign") }
- it "should do nothing if no autosign.conf exists" do
- Puppet[:autosign] = autosign
- FileTest.expects(:exist?).with(autosign).returns false
+ it "should do nothing if autosign is disabled" do
+ Puppet[:autosign] = false
- Puppet::SSL::CertificateRequest.indirection.expects(:search).never
- @ca.autosign
- end
+ @ca.expects(:sign).never
+ @ca.autosign(csr)
+ end
- describe "and autosign is enabled and the autosign.conf file exists" do
- before do
+ it "should do nothing if no autosign.conf exists" do
Puppet[:autosign] = autosign
- FileTest.stubs(:exist?).with(autosign).returns true
- File.stubs(:readlines).with(autosign).returns ["one\n", "two\n"]
+ non_existent_file = Puppet::FileSystem::MemoryFile.a_missing_file(autosign)
+ Puppet::FileSystem::File.overlay(non_existent_file) do
+ @ca.expects(:sign).never
+ @ca.autosign(csr)
+ end
+ end
- Puppet::SSL::CertificateRequest.indirection.stubs(:search).returns []
+ describe "and autosign is enabled and the autosign.conf file exists" do
+ let(:store) { stub 'store', :allow => nil, :allowed? => false }
- @store = stub 'store', :allow => nil
- Puppet::Network::AuthStore.stubs(:new).returns @store
- end
+ before do
+ Puppet[:autosign] = autosign
+ end
- describe "when creating the AuthStore instance to verify autosigning" do
- it "should create an AuthStore with each line in the configuration file allowed to be autosigned" do
- Puppet::Network::AuthStore.expects(:new).returns @store
+ describe "when creating the AuthStore instance to verify autosigning" do
+ it "should create an AuthStore with each line in the configuration file allowed to be autosigned" do
+ Puppet::FileSystem::File.overlay(Puppet::FileSystem::MemoryFile.a_regular_file_containing(autosign, "one\ntwo\n")) do
+ Puppet::Network::AuthStore.stubs(:new).returns store
- @store.expects(:allow).with("one")
- @store.expects(:allow).with("two")
+ store.expects(:allow).with("one")
+ store.expects(:allow).with("two")
- @ca.autosign
- end
+ @ca.autosign(csr)
+ end
+ end
- it "should reparse the autosign configuration on each call" do
- Puppet::Network::AuthStore.expects(:new).times(2).returns @store
+ it "should reparse the autosign configuration on each call" do
+ Puppet::FileSystem::File.overlay(Puppet::FileSystem::MemoryFile.a_regular_file_containing(autosign, "one")) do
+ Puppet::Network::AuthStore.stubs(:new).times(2).returns store
- @ca.autosign
- @ca.autosign
- end
+ @ca.autosign(csr)
+ @ca.autosign(csr)
+ end
+ end
- it "should ignore comments" do
- File.stubs(:readlines).with(autosign).returns ["one\n", "#two\n"]
+ it "should ignore comments" do
+ Puppet::FileSystem::File.overlay(Puppet::FileSystem::MemoryFile.a_regular_file_containing(autosign, "one\n#two\n")) do
+ Puppet::Network::AuthStore.stubs(:new).returns store
- @store.expects(:allow).with("one")
- @ca.autosign
- end
+ store.expects(:allow).with("one")
- it "should ignore blank lines" do
- File.stubs(:readlines).with(autosign).returns ["one\n", "\n"]
+ @ca.autosign(csr)
+ end
+ end
- @store.expects(:allow).with("one")
- @ca.autosign
+ it "should ignore blank lines" do
+ Puppet::FileSystem::File.overlay(Puppet::FileSystem::MemoryFile.a_regular_file_containing(autosign, "one\n\n")) do
+ Puppet::Network::AuthStore.stubs(:new).returns store
+
+ store.expects(:allow).with("one")
+ @ca.autosign(csr)
+ end
+ end
end
end
+ end
+
+ describe "using the autosign command setting" do
+ let(:cmd) { File.expand_path('/autosign_cmd') }
+ let(:autosign_cmd) { mock 'autosign_command' }
+ let(:autosign_executable) { Puppet::FileSystem::MemoryFile.an_executable(cmd) }
+
+ before do
+ Puppet[:autosign] = cmd
+
+ Puppet::SSL::CertificateAuthority::AutosignCommand.stubs(:new).returns autosign_cmd
+ end
- it "should sign all CSRs whose hostname matches the autosign configuration" do
- csr1 = mock 'csr1'
- csr2 = mock 'csr2'
- Puppet::SSL::CertificateRequest.indirection.stubs(:search).returns [csr1, csr2]
+ it "autosigns the CSR if the autosign command returned true" do
+ Puppet::FileSystem::File.overlay(autosign_executable) do
+ autosign_cmd.expects(:allowed?).with(csr).returns true
+
+ @ca.expects(:sign).with('host')
+ @ca.autosign(csr)
+ end
end
- it "should not sign CSRs whose hostname does not match the autosign configuration" do
- csr1 = mock 'csr1'
- csr2 = mock 'csr2'
- Puppet::SSL::CertificateRequest.indirection.stubs(:search).returns [csr1, csr2]
+ it "doesn't autosign the CSR if the autosign_command returned false" do
+ Puppet::FileSystem::File.overlay(autosign_executable) do
+ autosign_cmd.expects(:allowed?).with(csr).returns false
+
+ @ca.expects(:sign).never
+ @ca.autosign(csr)
+ end
end
end
end
@@ -701,28 +723,6 @@ describe Puppet::SSL::CertificateAuthority do
@ca = Puppet::SSL::CertificateAuthority.new
end
- it "should have a method for acting on the SSL files" do
- @ca.should respond_to(:apply)
- end
-
- describe "when applying a method to a set of hosts" do
- it "should fail if no subjects have been specified" do
- expect { @ca.apply(:generate) }.to raise_error(ArgumentError)
- end
-
- it "should create an Interface instance with the specified method and the options" do
- Puppet::SSL::CertificateAuthority::Interface.expects(:new).with(:generate, :to => :host).returns(stub('applier', :apply => nil))
- @ca.apply(:generate, :to => :host)
- end
-
- it "should apply the Interface with itself as the argument" do
- applier = stub('applier')
- applier.expects(:apply).with(@ca)
- Puppet::SSL::CertificateAuthority::Interface.expects(:new).returns applier
- @ca.apply(:generate, :to => :ca_testing)
- end
- end
-
it "should be able to list waiting certificate requests" do
req1 = stub 'req1', :name => "one"
req2 = stub 'req2', :name => "two"
@@ -979,16 +979,15 @@ require 'puppet/indirector/memory'
describe "CertificateAuthority.generate" do
def expect_to_increment_serial_file
- Puppet.settings.expects(:readwritelock).with(:serial)
+ Puppet.settings.setting(:serial).expects(:exclusive_open)
end
def expect_to_sign_a_cert
expect_to_increment_serial_file
- Puppet.settings.expects(:write).with(:cert_inventory, "a")
end
def expect_to_write_the_ca_password
- Puppet.settings.expects(:write).with(:capass)
+ Puppet.settings.setting(:capass).expects(:open).with('w')
end
def expect_ca_initialization
@@ -996,10 +995,6 @@ describe "CertificateAuthority.generate" do
expect_to_sign_a_cert
end
- def avoid_rebuilding_inventory_for_every_cert
- Puppet::SSL::Inventory.any_instance.stubs(:rebuild)
- end
-
INDIRECTED_CLASSES = [
Puppet::SSL::Certificate,
Puppet::SSL::CertificateRequest,
@@ -1021,7 +1016,7 @@ describe "CertificateAuthority.generate" do
end
before do
- avoid_rebuilding_inventory_for_every_cert
+ Puppet::SSL::Inventory.stubs(:new).returns(stub("Inventory", :add => nil))
INDIRECTED_CLASSES.each { |const| const.indirection.terminus_class = :memory }
end
@@ -1036,7 +1031,7 @@ describe "CertificateAuthority.generate" do
let(:ca) { Puppet::SSL::CertificateAuthority.new }
before do
- expect_ca_initialization
+ expect_ca_initialization
end
it "should fail if a certificate already exists for the host" do
diff --git a/spec/unit/ssl/certificate_factory_spec.rb b/spec/unit/ssl/certificate_factory_spec.rb
index 85609593a..fa436edcf 100755
--- a/spec/unit/ssl/certificate_factory_spec.rb
+++ b/spec/unit/ssl/certificate_factory_spec.rb
@@ -115,6 +115,24 @@ describe Puppet::SSL::CertificateFactory do
end
end
+ it "can add custom extension requests" do
+ csr = Puppet::SSL::CertificateRequest.new(name)
+ csr.generate(key)
+
+ csr.stubs(:request_extensions).returns([
+ {'oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'some-value'},
+ {'oid' => 'pp_uuid', 'value' => 'some-uuid'},
+ ])
+
+ cert = subject.build(:client, csr, issuer, serial)
+
+ priv_ext = cert.extensions.find {|ext| ext.oid == '1.3.6.1.4.1.34380.1.2.1'}
+ uuid_ext = cert.extensions.find {|ext| ext.oid == 'pp_uuid'}
+
+ expect(priv_ext.value).to eq 'some-value'
+ expect(uuid_ext.value).to eq 'some-uuid'
+ end
+
# Can't check the CA here, since that requires way more infrastructure
# that I want to build up at this time. We can verify the critical
# values, though, which are non-CA certs. --daniel 2011-10-11
diff --git a/spec/unit/ssl/certificate_request_attributes_spec.rb b/spec/unit/ssl/certificate_request_attributes_spec.rb
new file mode 100644
index 000000000..6165330aa
--- /dev/null
+++ b/spec/unit/ssl/certificate_request_attributes_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+require 'puppet/ssl/certificate_request_attributes'
+
+describe Puppet::SSL::CertificateRequestAttributes do
+
+ let(:expected) do
+ {
+ "custom_attributes" => {
+ "1.3.6.1.4.1.34380.2.2"=>[3232235521, 3232235777], # system IPs in hex
+ "1.3.6.1.4.1.34380.2.0"=>"hostname.domain.com",
+ }
+ }
+ end
+ let(:csr_attributes_hash) { expected.dup }
+ let(:csr_attributes_path) { '/some/where/csr_attributes.yaml' }
+ let(:csr_attributes) { Puppet::SSL::CertificateRequestAttributes.new(csr_attributes_path) }
+
+ it "initializes with a path" do
+ expect(csr_attributes.path).to eq(csr_attributes_path)
+ end
+
+ describe "loading" do
+ it "returns nil when loading from a non-existent file" do
+ expect(csr_attributes.load).to be_false
+ end
+
+ context "with an available attributes file" do
+ before do
+ Puppet::FileSystem::File.expects(:exist?).with(csr_attributes_path).returns(true)
+ Puppet::Util::Yaml.expects(:load_file).with(csr_attributes_path, {}).returns(csr_attributes_hash)
+ end
+
+ it "loads csr attributes from a file when the file is present" do
+ expect(csr_attributes.load).to be_true
+ end
+
+ it "exposes custom_attributes" do
+ csr_attributes.load
+ expect(csr_attributes.custom_attributes).to eq(expected['custom_attributes'])
+ end
+
+ it "returns an empty hash if custom_attributes points to nil" do
+ csr_attributes_hash["custom_attributes"] = nil
+ csr_attributes.load
+ expect(csr_attributes.custom_attributes).to eq({})
+ end
+
+ it "returns an empty hash if custom_attributes key is not present" do
+ csr_attributes_hash.delete("custom_attributes")
+ csr_attributes.load
+ expect(csr_attributes.custom_attributes).to eq({})
+ end
+
+ it "raise a Puppet::Error if an unexpected root key is defined" do
+ csr_attributes_hash['unintentional'] = 'data'
+ expect { csr_attributes.load }.to raise_error(Puppet::Error, /unexpected attributes.*unintentional/)
+ end
+ end
+ end
+end
diff --git a/spec/unit/ssl/certificate_request_spec.rb b/spec/unit/ssl/certificate_request_spec.rb
index 1dc449d53..192c929b5 100755
--- a/spec/unit/ssl/certificate_request_spec.rb
+++ b/spec/unit/ssl/certificate_request_spec.rb
@@ -178,6 +178,109 @@ describe Puppet::SSL::CertificateRequest do
end
end
+ context "with custom CSR attributes" do
+
+ it "adds attributes with single values" do
+ csr_attributes = {
+ '1.3.6.1.4.1.34380.1.2.1' => 'CSR specific info',
+ '1.3.6.1.4.1.34380.1.2.2' => 'more CSR specific info',
+ }
+
+ request.generate(key, :csr_attributes => csr_attributes)
+
+ attrs = request.custom_attributes
+ attrs.should include({'oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'CSR specific info'})
+ attrs.should include({'oid' => '1.3.6.1.4.1.34380.1.2.2', 'value' => 'more CSR specific info'})
+ end
+
+ ['extReq', '1.2.840.113549.1.9.14'].each do |oid|
+ it "doesn't overwrite standard PKCS#9 CSR attribute '#{oid}'" do
+ expect do
+ request.generate(key, :csr_attributes => {oid => 'data'})
+ end.to raise_error ArgumentError, /Cannot specify.*#{oid}/
+ end
+ end
+
+ ['msExtReq', '1.3.6.1.4.1.311.2.1.14'].each do |oid|
+ it "doesn't overwrite Microsoft extension request OID '#{oid}'" do
+ expect do
+ request.generate(key, :csr_attributes => {oid => 'data'})
+ end.to raise_error ArgumentError, /Cannot specify.*#{oid}/
+ end
+ end
+
+ it "raises an error if an attribute cannot be created" do
+ csr_attributes = { "thats.no.moon" => "death star" }
+
+ expect do
+ request.generate(key, :csr_attributes => csr_attributes)
+ end.to raise_error Puppet::Error, /Cannot create CSR with attribute thats\.no\.moon: first num too large/
+ end
+ end
+
+ context "with extension requests" do
+ let(:extension_data) do
+ {
+ '1.3.6.1.4.1.34380.1.1.31415' => 'pi',
+ '1.3.6.1.4.1.34380.1.1.2718' => 'e',
+ }
+ end
+
+ it "adds an extreq attribute to the CSR" do
+ request.generate(key, :extension_requests => extension_data)
+
+ exts = request.content.attributes.select { |attr| attr.oid = 'extReq' }
+ exts.length.should == 1
+ end
+
+ it "adds an extension for each entry in the extension request structure" do
+ request.generate(key, :extension_requests => extension_data)
+
+ exts = request.request_extensions
+
+ exts.should include('oid' => '1.3.6.1.4.1.34380.1.1.31415', 'value' => 'pi')
+ exts.should include('oid' => '1.3.6.1.4.1.34380.1.1.2718', 'value' => 'e')
+ end
+
+ it "defines the extensions as non-critical" do
+ request.generate(key, :extension_requests => extension_data)
+ request.request_extensions.each do |ext|
+ ext['critical'].should be_false
+ end
+ end
+
+ it "rejects the subjectAltNames extension" do
+ san_names = ['subjectAltName', '2.5.29.17']
+ san_field = 'DNS:first.tld, DNS:second.tld'
+
+ san_names.each do |name|
+ expect do
+ request.generate(key, :extension_requests => {name => san_field})
+ end.to raise_error Puppet::Error, /conflicts with internally used extension/
+ end
+ end
+
+ it "merges the extReq attribute with the subjectAltNames extension" do
+ request.generate(key,
+ :dns_alt_names => 'first.tld, second.tld',
+ :extension_requests => extension_data)
+ exts = request.request_extensions
+
+ exts.should include('oid' => '1.3.6.1.4.1.34380.1.1.31415', 'value' => 'pi')
+ exts.should include('oid' => '1.3.6.1.4.1.34380.1.1.2718', 'value' => 'e')
+ exts.should include('oid' => 'subjectAltName', 'value' => 'DNS:first.tld, DNS:myname, DNS:second.tld')
+
+ request.subject_alt_names.should eq ['DNS:first.tld', 'DNS:myname', 'DNS:second.tld']
+ end
+
+ it "raises an error if the OID could not be created" do
+ exts = {"thats.no.moon" => "death star"}
+ expect do
+ request.generate(key, :extension_requests => exts)
+ end.to raise_error Puppet::Error, /Cannot create CSR with extension request thats\.no\.moon: first num too large/
+ end
+ end
+
it "should sign the csr with the provided key" do
request.generate(key)
request.content.verify(key.content.public_key).should be_true
diff --git a/spec/unit/ssl/certificate_spec.rb b/spec/unit/ssl/certificate_spec.rb
index 70d35d4c7..c8f9930f3 100755
--- a/spec/unit/ssl/certificate_spec.rb
+++ b/spec/unit/ssl/certificate_spec.rb
@@ -75,6 +75,17 @@ describe Puppet::SSL::Certificate do
end
describe "when managing instances" do
+
+ def build_cert(opts)
+ key = Puppet::SSL::Key.new('quux')
+ key.generate
+ csr = Puppet::SSL::CertificateRequest.new('quux')
+ csr.generate(key, opts)
+
+ raw_cert = Puppet::SSL::CertificateFactory.build('client', csr, csr.content, 14)
+ @class.from_instance(raw_cert)
+ end
+
before do
@certificate = @class.new("myname")
end
@@ -93,33 +104,35 @@ describe Puppet::SSL::Certificate do
describe "#subject_alt_names" do
it "should list all alternate names when the extension is present" do
- key = Puppet::SSL::Key.new('quux')
- key.generate
-
- csr = Puppet::SSL::CertificateRequest.new('quux')
- csr.generate(key, :dns_alt_names => 'foo, bar,baz')
-
- raw_csr = csr.content
-
- cert = Puppet::SSL::CertificateFactory.build('server', csr, raw_csr, 14)
- certificate = @class.from_s(cert.to_pem)
+ certificate = build_cert(:dns_alt_names => 'foo, bar,baz')
certificate.subject_alt_names.
should =~ ['DNS:foo', 'DNS:bar', 'DNS:baz', 'DNS:quux']
end
it "should return an empty list of names if the extension is absent" do
- key = Puppet::SSL::Key.new('quux')
- key.generate
+ certificate = build_cert({})
+ certificate.subject_alt_names.should be_empty
+ end
+ end
- csr = Puppet::SSL::CertificateRequest.new('quux')
- csr.generate(key)
+ describe "custom extensions" do
+ it "returns extensions under the ppRegCertExt" do
+ exts = {'pp_uuid' => 'abcdfd'}
+ cert = build_cert(:extension_requests => exts)
+ expect(cert.custom_extensions).to include('oid' => 'pp_uuid', 'value' => 'abcdfd')
+ end
- raw_csr = csr.content
+ it "returns extensions under the ppPrivCertExt" do
+ exts = {'1.3.6.1.4.1.34380.1.2.1' => 'x509 :('}
+ cert = build_cert(:extension_requests => exts)
+ expect(cert.custom_extensions).to include('oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'x509 :(')
+ end
- cert = Puppet::SSL::CertificateFactory.build('client', csr, raw_csr, 14)
- certificate = @class.from_s(cert.to_pem)
- certificate.subject_alt_names.should be_empty
+ it "doesn't return standard extensions" do
+ cert = build_cert(:dns_alt_names => 'foo')
+ expect(cert.custom_extensions).to be_empty
end
+
end
it "should return a nil expiration if there is no actual certificate" do
diff --git a/spec/unit/ssl/host_spec.rb b/spec/unit/ssl/host_spec.rb
index 8240991c7..3b341cc4e 100755
--- a/spec/unit/ssl/host_spec.rb
+++ b/spec/unit/ssl/host_spec.rb
@@ -9,9 +9,24 @@ def base_pson_comparison(result, pson_hash)
result["state"].should == pson_hash["desired_state"]
end
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ HOST_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__), '../../../api/schemas/host.json')))
+
+ describe "host schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, HOST_SCHEMA)
+ end
+ end
+end
+
describe Puppet::SSL::Host do
include PuppetSpec::Files
+ def validate_json_for_host(host)
+ JSON::Validator.validate!(HOST_SCHEMA, host.to_pson)
+ end
+
before do
Puppet::SSL::Host.indirection.terminus_class = :file
@@ -823,7 +838,7 @@ describe Puppet::SSL::Host do
let(:host) do
Puppet::SSL::Host.new("bazinga")
end
-
+
let(:pson_hash) do
{
"fingerprint" => host.certificate_request.fingerprint,
@@ -831,15 +846,20 @@ describe Puppet::SSL::Host do
"name" => host.name
}
end
-
+
it "should be able to identify a host with an unsigned certificate request" do
host.generate_certificate_request
result = PSON.parse(Puppet::SSL::Host.new(host.name).to_pson)
-
+
base_pson_comparison result, pson_hash
end
-
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ host.generate_certificate_request
+ validate_json_for_host(host)
+ end
+
describe "explicit fingerprints" do
[:SHA1, :SHA256, :SHA512].each do |md|
it "should include #{md}" do
@@ -854,7 +874,7 @@ describe Puppet::SSL::Host do
end
end
end
-
+
describe "dns_alt_names" do
describe "when not specified" do
it "should include the dns_alt_names associated with the certificate" do
@@ -867,22 +887,28 @@ describe Puppet::SSL::Host do
end
end
- [ "",
+ [ "",
"test, alt, names"
].each do |alt_names|
describe "when #{alt_names}" do
- it "should include the dns_alt_names associated with the certificate" do
+ before(:each) do
host.generate_certificate_request :dns_alt_names => alt_names
+ end
+
+ it "should include the dns_alt_names associated with the certificate" do
pson_hash["desired_alt_names"] = host.certificate_request.subject_alt_names
result = PSON.parse(Puppet::SSL::Host.new(host.name).to_pson)
base_pson_comparison result, pson_hash
result["dns_alt_names"].should == pson_hash["desired_alt_names"]
end
+
+ it "should validate against the schema", :unless => Puppet.features.microsoft_windows? do
+ validate_json_for_host(host)
+ end
end
end
end
-
it "should be able to identify a host with a signed certificate" do
host.generate_certificate_request
diff --git a/spec/unit/ssl/inventory_spec.rb b/spec/unit/ssl/inventory_spec.rb
index b145cd9ab..9bcbbcea5 100755
--- a/spec/unit/ssl/inventory_spec.rb
+++ b/spec/unit/ssl/inventory_spec.rb
@@ -20,7 +20,7 @@ describe Puppet::SSL::Inventory, :unless => Puppet.features.microsoft_windows? d
before do
Puppet[:cert_inventory] = cert_inventory
- FileTest.stubs(:exist?).with(cert_inventory).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(cert_inventory).returns true
@inventory = @class.new
@@ -28,86 +28,51 @@ describe Puppet::SSL::Inventory, :unless => Puppet.features.microsoft_windows? d
end
describe "and creating the inventory file" do
- before do
- Puppet.settings.stubs(:write)
- FileTest.stubs(:exist?).with(cert_inventory).returns false
-
- Puppet::SSL::Certificate.indirection.stubs(:search).returns []
- end
-
- it "should log that it is building a new inventory file" do
- Puppet.expects(:notice)
-
- @inventory.rebuild
- end
-
- it "should use the Settings to write to the file" do
- Puppet.settings.expects(:write).with(:cert_inventory)
-
- @inventory.rebuild
- end
-
- it "should add a header to the file" do
- fh = mock 'filehandle'
- Puppet.settings.stubs(:write).yields fh
- fh.expects(:print).with { |str| str =~ /^#/ }
-
- @inventory.rebuild
- end
-
- it "should add formatted information on all existing certificates" do
- cert1 = mock 'cert1'
- cert2 = mock 'cert2'
-
+ it "re-adds all of the existing certificates" do
+ inventory_file = StringIO.new
+ Puppet.settings.setting(:cert_inventory).stubs(:open).yields(inventory_file)
+
+ cert1 = Puppet::SSL::Certificate.new("cert1")
+ cert1.content = stub 'cert1',
+ :serial => 2,
+ :not_before => Time.now,
+ :not_after => Time.now,
+ :subject => "/CN=smocking"
+ cert2 = Puppet::SSL::Certificate.new("cert2")
+ cert2.content = stub 'cert2',
+ :serial => 3,
+ :not_before => Time.now,
+ :not_after => Time.now,
+ :subject => "/CN=mocking bird"
Puppet::SSL::Certificate.indirection.expects(:search).with("*").returns [cert1, cert2]
- @class.any_instance.expects(:add).with(cert1)
- @class.any_instance.expects(:add).with(cert2)
-
@inventory.rebuild
+
+ expect(inventory_file.string).to match(/\/CN=smocking/)
+ expect(inventory_file.string).to match(/\/CN=mocking bird/)
end
end
describe "and adding a certificate" do
- it "should build the inventory file if one does not exist" do
- Puppet[:cert_inventory] = cert_inventory
- Puppet.settings.stubs(:write)
-
- FileTest.expects(:exist?).with(cert_inventory).returns false
-
- @inventory.expects(:rebuild)
-
- @inventory.add(@cert)
- end
it "should use the Settings to write to the file" do
- Puppet.settings.expects(:write).with(:cert_inventory, "a")
+ Puppet.settings.setting(:cert_inventory).expects(:open).with("a")
@inventory.add(@cert)
end
- it "should use the actual certificate if it was passed a Puppet certificate" do
+ it "should add formatted certificate information to the end of the file" do
cert = Puppet::SSL::Certificate.new("mycert")
cert.content = @cert
- fh = stub 'filehandle', :print => nil
- Puppet.settings.stubs(:write).yields fh
-
- @inventory.expects(:format).with(@cert)
-
- @inventory.add(@cert)
- end
-
- it "should add formatted certificate information to the end of the file" do
- fh = mock 'filehandle'
-
- Puppet.settings.stubs(:write).yields fh
+ fh = StringIO.new
+ Puppet.settings.setting(:cert_inventory).expects(:open).with("a").yields(fh)
@inventory.expects(:format).with(@cert).returns "myformat"
- fh.expects(:print).with("myformat")
-
@inventory.add(@cert)
+
+ expect(fh.string).to eq("myformat")
end
end
@@ -152,7 +117,7 @@ describe Puppet::SSL::Inventory, :unless => Puppet.features.microsoft_windows? d
describe "and finding a serial number" do
it "should return nil if the inventory file is missing" do
- FileTest.expects(:exist?).with(cert_inventory).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(cert_inventory).returns false
@inventory.serial(:whatever).should be_nil
end
diff --git a/spec/unit/ssl/key_spec.rb b/spec/unit/ssl/key_spec.rb
index 112505087..4cea5491c 100755
--- a/spec/unit/ssl/key_spec.rb
+++ b/spec/unit/ssl/key_spec.rb
@@ -71,7 +71,7 @@ describe Puppet::SSL::Key do
end
it "should not try to use the provided password file if the file does not exist" do
- FileTest.stubs(:exist?).returns false
+ Puppet::FileSystem::File.stubs(:exist?).returns false
@key.password_file = "/path/to/password"
path = "/my/path"
@@ -84,7 +84,7 @@ describe Puppet::SSL::Key do
end
it "should read the key with the password retrieved from the password file if one is provided" do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
@key.password_file = "/path/to/password"
path = "/my/path"
@@ -154,7 +154,7 @@ describe Puppet::SSL::Key do
describe "with a password file set" do
it "should return a nil password if the password file does not exist" do
- FileTest.expects(:exist?).with("/path/to/pass").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("/path/to/pass").returns false
File.expects(:read).with("/path/to/pass").never
@instance.password_file = "/path/to/pass"
@@ -163,7 +163,7 @@ describe Puppet::SSL::Key do
end
it "should return the contents of the password file as its password" do
- FileTest.expects(:exist?).with("/path/to/pass").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/path/to/pass").returns true
File.expects(:read).with("/path/to/pass").returns "my password"
@instance.password_file = "/path/to/pass"
diff --git a/spec/unit/ssl/oids_spec.rb b/spec/unit/ssl/oids_spec.rb
new file mode 100644
index 000000000..ee95bb942
--- /dev/null
+++ b/spec/unit/ssl/oids_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+require 'puppet/ssl/oids'
+
+describe Puppet::SSL::Oids do
+ describe "defining application OIDs" do
+
+ {
+ 'puppetlabs' => '1.3.6.1.4.1.34380',
+ 'ppCertExt' => '1.3.6.1.4.1.34380.1',
+ 'ppRegCertExt' => '1.3.6.1.4.1.34380.1.1',
+ 'pp_uuid' => '1.3.6.1.4.1.34380.1.1.1',
+ 'pp_instance_id' => '1.3.6.1.4.1.34380.1.1.2',
+ 'pp_image_name' => '1.3.6.1.4.1.34380.1.1.3',
+ 'pp_preshared_key' => '1.3.6.1.4.1.34380.1.1.4',
+ 'ppPrivCertExt' => '1.3.6.1.4.1.34380.1.2',
+ }.each_pair do |sn, oid|
+ it "defines #{sn} as #{oid}" do
+ object_id = OpenSSL::ASN1::ObjectId.new(sn)
+ expect(object_id.oid).to eq oid
+ end
+ end
+ end
+
+ describe "checking if an OID is a subtree of another OID" do
+
+ it "can determine if an OID is contained in another OID" do
+ described_class.subtree_of?('1.3.6.1', '1.3.6.1.4.1').should be_true
+ described_class.subtree_of?('1.3.6.1.4.1', '1.3.6.1').should be_false
+ end
+
+ it "returns true if an OID is compared against itself and exclusive is false" do
+ described_class.subtree_of?('1.3.6.1', '1.3.6.1', false).should be_true
+ end
+
+ it "returns false if an OID is compared against itself and exclusive is true" do
+ described_class.subtree_of?('1.3.6.1', '1.3.6.1', true).should be_false
+ end
+
+ it "can compare OIDs defined as short names" do
+ described_class.subtree_of?('IANA', '1.3.6.1.4.1').should be_true
+ described_class.subtree_of?('1.3.6.1', 'enterprises').should be_true
+ end
+
+ it "returns false when an invalid OID shortname is passed" do
+ described_class.subtree_of?('IANA', 'bananas').should be_false
+ end
+ end
+end
diff --git a/spec/unit/ssl/validator_spec.rb b/spec/unit/ssl/validator_spec.rb
index fe0904cb8..2b8cfb0f9 100644
--- a/spec/unit/ssl/validator_spec.rb
+++ b/spec/unit/ssl/validator_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
-require 'puppet/ssl/validator'
+require 'puppet/ssl'
require 'puppet/ssl/configuration'
-describe Puppet::SSL::Validator do
+describe Puppet::SSL::Validator::DefaultValidator do
let(:ssl_context) do
mock('OpenSSL::X509::StoreContext')
end
@@ -14,8 +14,16 @@ describe Puppet::SSL::Validator do
:ca_auth_file => Puppet[:ssl_client_ca_auth])
end
+ let(:ssl_host) do
+ stub('ssl_host',
+ :ssl_store => nil,
+ :certificate => stub('cert', :content => nil),
+ :key => stub('key', :content => nil))
+ end
+
subject do
- described_class.new(:ssl_configuration => ssl_configuration)
+ described_class.new(ssl_configuration,
+ ssl_host)
end
before :each do
@@ -49,17 +57,20 @@ describe Puppet::SSL::Validator do
before :each do
ssl_context.stubs(:error_string).returns("Something went wrong.")
end
+
it 'does not make the error available via #verify_errors' do
subject.call(true, ssl_context)
subject.verify_errors.should == []
end
end
+
context 'and the chain is valid' do
it 'is true for each CA certificate in the chain' do
(cert_chain.length - 1).times do
subject.call(true, ssl_context).should be_true
end
end
+
it 'is true for the SSL certificate ending the chain' do
(cert_chain.length - 1).times do
subject.call(true, ssl_context)
@@ -67,17 +78,20 @@ describe Puppet::SSL::Validator do
subject.call(true, ssl_context).should be_true
end
end
+
context 'and the chain is invalid' do
before :each do
ssl_configuration.stubs(:read_file).
with(Puppet[:localcacert]).
returns(agent_ca)
end
+
it 'is true for each CA certificate in the chain' do
(cert_chain.length - 1).times do
subject.call(true, ssl_context).should be_true
end
end
+
it 'is false for the SSL certificate ending the chain' do
(cert_chain.length - 1).times do
subject.call(true, ssl_context)
@@ -85,13 +99,16 @@ describe Puppet::SSL::Validator do
subject.call(true, ssl_context).should be_false
end
end
+
context 'an error is raised inside of #call' do
before :each do
ssl_context.expects(:current_cert).raises(StandardError, "BOOM!")
end
+
it 'is false' do
subject.call(true, ssl_context).should be_false
end
+
it 'makes the error available through #verify_errors' do
subject.call(true, ssl_context)
subject.verify_errors.should == ["BOOM!"]
@@ -100,11 +117,28 @@ describe Puppet::SSL::Validator do
end
end
- describe '#register_verify_callback' do
- it 'registers itself using #verify_callback' do
+ describe '#setup_connection' do
+ it 'updates the connection for verification' do
+ subject.stubs(:ssl_certificates_are_present?).returns(true)
connection = mock('Net::HTTP')
+
+ connection.expects(:cert_store=).with(ssl_host.ssl_store)
+ connection.expects(:ca_file=).with(ssl_configuration.ca_auth_file)
+ connection.expects(:cert=).with(ssl_host.certificate.content)
+ connection.expects(:key=).with(ssl_host.key.content)
connection.expects(:verify_callback=).with(subject)
- subject.register_verify_callback(connection)
+ connection.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
+
+ subject.setup_connection(connection)
+ end
+
+ it 'does not perform verification if certificate files are missing' do
+ subject.stubs(:ssl_certificates_are_present?).returns(false)
+ connection = mock('Net::HTTP')
+
+ connection.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+
+ subject.setup_connection(connection)
end
end
@@ -120,17 +154,21 @@ describe Puppet::SSL::Validator do
before :each do
subject.stubs(:has_authz_peer_cert).returns(true)
end
+
it 'is true' do
subject.valid_peer?.should be_true
end
end
+
context 'when the peer presents an invalid chain' do
before :each do
subject.stubs(:has_authz_peer_cert).returns(false)
end
+
it 'is false' do
subject.valid_peer?.should be_false
end
+
it 'makes a helpful error message available via #verify_errors' do
subject.valid_peer?
subject.verify_errors.should == [expected_authz_error_msg]
@@ -143,22 +181,27 @@ describe Puppet::SSL::Validator do
it 'returns true when the SSL cert is issued by the Master CA' do
subject.has_authz_peer_cert(cert_chain, [root_ca_cert]).should be_true
end
+
it 'returns true when the SSL cert is issued by the Agent CA' do
subject.has_authz_peer_cert(cert_chain_agent_ca, [root_ca_cert]).should be_true
end
end
+
context 'when the Master CA is listed as authorized' do
it 'returns false when the SSL cert is issued by the Master CA' do
subject.has_authz_peer_cert(cert_chain, [master_ca_cert]).should be_true
end
+
it 'returns true when the SSL cert is issued by the Agent CA' do
subject.has_authz_peer_cert(cert_chain_agent_ca, [master_ca_cert]).should be_false
end
end
+
context 'when the Agent CA is listed as authorized' do
it 'returns true when the SSL cert is issued by the Master CA' do
subject.has_authz_peer_cert(cert_chain, [agent_ca_cert]).should be_false
end
+
it 'returns true when the SSL cert is issued by the Agent CA' do
subject.has_authz_peer_cert(cert_chain_agent_ca, [agent_ca_cert]).should be_true
end
diff --git a/spec/unit/status_spec.rb b/spec/unit/status_spec.rb
index 3f6ae7d82..8f598f579 100755
--- a/spec/unit/status_spec.rb
+++ b/spec/unit/status_spec.rb
@@ -37,4 +37,13 @@ describe Puppet::Status do
new_status = Puppet::Status.convert_from('yaml', status.render('yaml'))
new_status.should equal_attributes_of(status)
end
+
+ it "serializes to PSON that conforms to the status schema", :unless => Puppet.features.microsoft_windows? do
+ schema = JSON.parse(File.read('api/schemas/status.json'))
+ status = Puppet::Status.new
+ status.version = Puppet.version
+
+ JSON::Validator.validate!(JSON_META_SCHEMA, schema)
+ JSON::Validator.validate!(schema, status.render('pson'))
+ end
end
diff --git a/spec/unit/transaction/event_spec.rb b/spec/unit/transaction/event_spec.rb
index a60e6e907..8e62e02f6 100755
--- a/spec/unit/transaction/event_spec.rb
+++ b/spec/unit/transaction/event_spec.rb
@@ -15,14 +15,6 @@ end
describe Puppet::Transaction::Event do
include PuppetSpec::Files
- [:previous_value, :desired_value, :property, :name, :message, :file, :line, :tags, :audited].each do |attr|
- it "should support #{attr}" do
- event = Puppet::Transaction::Event.new
- event.send(attr.to_s + "=", "foo")
- event.send(attr).should == "foo"
- end
- end
-
it "should support resource" do
event = Puppet::Transaction::Event.new
event.resource = TestResource.new
@@ -101,7 +93,7 @@ describe Puppet::Transaction::Event do
end
it "should set the tags to the event tags" do
- Puppet::Util::Log.expects(:new).with { |args| args[:tags] == %w{one two} }
+ Puppet::Util::Log.expects(:new).with { |args| args[:tags].to_a.should =~ %w{one two} }
Puppet::Transaction::Event.new(:tags => %w{one two}).send_log
end
diff --git a/spec/unit/transaction/report_spec.rb b/spec/unit/transaction/report_spec.rb
index 7195b0623..661349dab 100755
--- a/spec/unit/transaction/report_spec.rb
+++ b/spec/unit/transaction/report_spec.rb
@@ -4,6 +4,19 @@ require 'spec_helper'
require 'puppet'
require 'puppet/transaction/report'
+# the json-schema gem doesn't support windows
+if not Puppet.features.microsoft_windows?
+ REPORT_SCHEMA_URI = File.join(File.dirname(__FILE__), '../../../api/schemas/report.json')
+ REPORT_SCHEMA = JSON.parse(File.read(REPORT_SCHEMA_URI))
+
+ describe "report schema" do
+ it "should validate against the json meta-schema" do
+ JSON::Validator.validate!(JSON_META_SCHEMA, REPORT_SCHEMA)
+ end
+ end
+
+end
+
describe Puppet::Transaction::Report do
include PuppetSpec::Files
before do
@@ -392,6 +405,12 @@ describe Puppet::Transaction::Report do
expect_equivalent_reports(tripped, report)
end
+ it "generates pson which validates against the report schema", :unless => Puppet.features.microsoft_windows? do
+ Puppet[:report_serialization_format] = "pson"
+ report = generate_report
+ JSON::Validator.validate!(REPORT_SCHEMA, report.render)
+ end
+
it "can make a round trip through yaml" do
Puppet[:report_serialization_format] = "yaml"
report = generate_report
@@ -458,7 +477,7 @@ describe Puppet::Transaction::Report do
status = Puppet::Resource::Status.new(Puppet::Type.type(:notify).new(:title => "a resource"))
status.changed = true
- report = Puppet::Transaction::Report.new('testy', 1357986, 'test_environment', "df34516e-4050-402d-a166-05b03b940749")
+ report = Puppet::Transaction::Report.new('apply', 1357986, 'test_environment', "df34516e-4050-402d-a166-05b03b940749")
report << Puppet::Util::Log.new(:level => :warning, :message => "log message")
report.add_times("timing", 4)
report.add_resource_status(status)
diff --git a/spec/unit/transaction/resource_harness_spec.rb b/spec/unit/transaction/resource_harness_spec.rb
index 0c250ae92..afe1ec912 100755
--- a/spec/unit/transaction/resource_harness_spec.rb
+++ b/spec/unit/transaction/resource_harness_spec.rb
@@ -127,6 +127,34 @@ describe Puppet::Transaction::ResourceHarness do
false
end
end
+
+ newproperty(:brillig) do
+ desc "A property that raises a StandardError exception when you test if it's insync?"
+ def sync
+ end
+
+ def retrieve
+ :absent
+ end
+
+ def insync?(reference_value)
+ raise ZeroDivisionError.new('brillig')
+ end
+ end
+
+ newproperty(:slithy) do
+ desc "A property that raises an Exception when you test if it's insync?"
+ def sync
+ end
+
+ def retrieve
+ :absent
+ end
+
+ def insync?(reference_value)
+ raise Exception.new('slithy')
+ end
+ end
end
stubProvider
end
@@ -164,6 +192,35 @@ describe Puppet::Transaction::ResourceHarness do
end
end
+ describe "when a StandardError exception occurs during insync?" do
+ before :each do
+ stub_provider = make_stub_provider
+ @resource = stub_provider.new :name => 'name', :brillig => 1
+ @resource.expects(:err).never
+ end
+
+ it "should record a failure event" do
+ @status = @harness.evaluate(@resource)
+ @status.events[0].name.to_s.should == 'brillig_changed'
+ @status.events[0].property.should == 'brillig'
+ @status.events[0].status.should == 'failure'
+ end
+ end
+
+ describe "when an Exception occurs during insync?" do
+ before :each do
+ stub_provider = make_stub_provider
+ @resource = stub_provider.new :name => 'name', :slithy => 1
+ @resource.expects(:err).never
+ end
+
+ it "should log and pass the exception through" do
+ lambda { @harness.evaluate(@resource) }.should raise_error(Exception, /slithy/)
+ @logs.first.message.should == "change from absent to 1 failed: slithy"
+ @logs.first.level.should == :err
+ end
+ end
+
describe "when auditing" do
it "should not call insync? on parameters that are merely audited" do
stub_provider = make_stub_provider
@@ -180,7 +237,9 @@ describe Puppet::Transaction::ResourceHarness do
File.open(test_file, 'w').close
resource = Puppet::Type.type(:file).new :path => test_file, :audit => ['group'], :backup => false
resource.expects(:err).never # make sure no exceptions get swallowed
+
status = @harness.evaluate(resource)
+
status.events.each do |event|
event.status.should != 'failure'
end
@@ -188,222 +247,13 @@ describe Puppet::Transaction::ResourceHarness do
end
describe "when applying changes" do
- [false, true].each do |noop_mode|; describe (noop_mode ? "in noop mode" : "in normal mode") do
- [nil, @mode_750].each do |machine_state|; describe (machine_state ? "with a file initially present" : "with no file initially present") do
- [nil, @mode_750, @mode_755].each do |yaml_mode|
- [nil, :file, :absent].each do |yaml_ensure|; describe "with mode=#{yaml_mode.inspect} and ensure=#{yaml_ensure.inspect} stored in state.yml" do
- [false, true].each do |auditing_ensure|
- [false, true].each do |auditing_mode|
- auditing = []
- auditing.push(:mode) if auditing_mode
- auditing.push(:ensure) if auditing_ensure
- [nil, :file, :absent].each do |ensure_property| # what we set "ensure" to in the manifest
- [nil, @mode_750, @mode_755].each do |mode_property| # what we set "mode" to in the manifest
- manifest_settings = {}
- manifest_settings[:audit] = auditing if !auditing.empty?
- manifest_settings[:ensure] = ensure_property if ensure_property
- manifest_settings[:mode] = mode_property if mode_property
- describe "with manifest settings #{manifest_settings.inspect}" do; it "should behave properly" do
- # Set up preconditions
- test_file = tmpfile('foo')
- if machine_state
- File.open(test_file, 'w', machine_state.to_i(8)).close
- end
-
- Puppet[:noop] = noop_mode
- params = { :path => test_file, :backup => false }
- params.merge!(manifest_settings)
- resource = Puppet::Type.type(:file).new params
-
- @harness.cache(resource, :mode, yaml_mode) if yaml_mode
- @harness.cache(resource, :ensure, yaml_ensure) if yaml_ensure
-
- fake_time = Time.utc(2011, 'jan', 3, 12, 24, 0)
- Time.stubs(:now).returns(fake_time) # So that Puppet::Resource::Status objects will compare properly
-
- resource.expects(:err).never # make sure no exceptions get swallowed
- status = @harness.evaluate(resource) # do the thing
-
- # check that the state of the machine has been properly updated
- expected_logs = []
- expected_status_events = []
- if auditing_mode
- @harness.cached(resource, :mode).should == (machine_state || :absent)
- else
- @harness.cached(resource, :mode).should == yaml_mode
- end
- if auditing_ensure
- @harness.cached(resource, :ensure).should == (machine_state ? :file : :absent)
- else
- @harness.cached(resource, :ensure).should == yaml_ensure
- end
- if ensure_property == :file
- file_would_be_there_if_not_noop = true
- elsif ensure_property == nil
- file_would_be_there_if_not_noop = machine_state != nil
- else # ensure_property == :absent
- file_would_be_there_if_not_noop = false
- end
- file_should_be_there = noop_mode ? machine_state != nil : file_would_be_there_if_not_noop
- File.exists?(test_file).should == file_should_be_there
- if file_should_be_there
- if noop_mode
- expected_file_mode = machine_state
- else
- expected_file_mode = mode_property || machine_state
- end
- if !expected_file_mode
- # we didn't specify a mode and the file was created, so mode comes from umode
- else
- file_mode = File.stat(test_file).mode & 0777
- file_mode.should == expected_file_mode.to_i(8)
- end
- end
-
- # Test log output for the "mode" parameter
- previously_recorded_mode_already_logged = false
- mode_status_msg = nil
- if machine_state && file_would_be_there_if_not_noop && mode_property && machine_state != mode_property
- if noop_mode
- what_happened = "current_value #{machine_state}, should be #{mode_property} (noop)"
- expected_status = 'noop'
- else
- what_happened = "mode changed '#{machine_state}' to '#{mode_property}'"
- expected_status = 'success'
- end
- if auditing_mode && yaml_mode && yaml_mode != machine_state
- previously_recorded_mode_already_logged = true
- mode_status_msg = "#{what_happened} (previously recorded value was #{yaml_mode})"
- else
- mode_status_msg = what_happened
- end
- expected_logs << "notice: /#{resource}/mode: #{mode_status_msg}"
- end
- if @harness.cached(resource, :mode) && @harness.cached(resource, :mode) != yaml_mode
- if yaml_mode
- unless previously_recorded_mode_already_logged
- mode_status_msg = "audit change: previously recorded value #{yaml_mode} has been changed to #{@harness.cached(resource, :mode)}"
- expected_logs << "notice: /#{resource}/mode: #{mode_status_msg}"
- expected_status = 'audit'
- end
- else
- expected_logs << "notice: /#{resource}/mode: audit change: newly-recorded value #{@harness.cached(resource, :mode)}"
- end
- end
- if mode_status_msg
- expected_status_events << Puppet::Transaction::Event.new(
- :source_description => "/#{resource}/mode", :resource => resource, :file => nil,
- :line => nil, :tags => %w{file}, :desired_value => mode_property,
- :historical_value => yaml_mode, :message => mode_status_msg, :name => :mode_changed,
- :previous_value => machine_state || :absent, :property => :mode, :status => expected_status,
- :audited => auditing_mode)
- end
-
- # Test log output for the "ensure" parameter
- previously_recorded_ensure_already_logged = false
- ensure_status_msg = nil
- if file_would_be_there_if_not_noop != (machine_state != nil)
- if noop_mode
- what_happened = "current_value #{machine_state ? 'file' : 'absent'}, should be #{file_would_be_there_if_not_noop ? 'file' : 'absent'} (noop)"
- expected_status = 'noop'
- else
- what_happened = file_would_be_there_if_not_noop ? 'created' : 'removed'
- expected_status = 'success'
- end
- if auditing_ensure && yaml_ensure && yaml_ensure != (machine_state ? :file : :absent)
- previously_recorded_ensure_already_logged = true
- ensure_status_msg = "#{what_happened} (previously recorded value was #{yaml_ensure})"
- else
- ensure_status_msg = "#{what_happened}"
- end
- expected_logs << "notice: /#{resource}/ensure: #{ensure_status_msg}"
- end
- if @harness.cached(resource, :ensure) && @harness.cached(resource, :ensure) != yaml_ensure
- if yaml_ensure
- unless previously_recorded_ensure_already_logged
- ensure_status_msg = "audit change: previously recorded value #{yaml_ensure} has been changed to #{@harness.cached(resource, :ensure)}"
- expected_logs << "notice: /#{resource}/ensure: #{ensure_status_msg}"
- expected_status = 'audit'
- end
- else
- expected_logs << "notice: /#{resource}/ensure: audit change: newly-recorded value #{@harness.cached(resource, :ensure)}"
- end
- end
- if ensure_status_msg
- if ensure_property == :file
- ensure_event_name = :file_created
- elsif ensure_property == nil
- ensure_event_name = :file_changed
- else # ensure_property == :absent
- ensure_event_name = :file_removed
- end
- expected_status_events << Puppet::Transaction::Event.new(
- :source_description => "/#{resource}/ensure", :resource => resource, :file => nil,
- :line => nil, :tags => %w{file}, :desired_value => ensure_property,
- :historical_value => yaml_ensure, :message => ensure_status_msg, :name => ensure_event_name,
- :previous_value => machine_state ? :file : :absent, :property => :ensure,
- :status => expected_status, :audited => auditing_ensure)
- end
-
- # Actually check the logs.
- @logs.map {|l| "#{l.level}: #{l.source}: #{l.message}"}.should =~ expected_logs
-
- # All the log messages should show up as events except the "newly-recorded" ones.
- expected_event_logs = @logs.reject {|l| l.message =~ /newly-recorded/ }
- status.events.map {|e| e.message}.should =~ expected_event_logs.map {|l| l.message }
- events_to_hash(status.events).should =~ events_to_hash(expected_status_events)
-
- # Check change count - this is the number of changes that actually occurred.
- expected_change_count = 0
- if (machine_state != nil) != file_should_be_there
- expected_change_count = 1
- elsif machine_state != nil
- if expected_file_mode != machine_state
- expected_change_count = 1
- end
- end
- status.change_count.should == expected_change_count
-
- # Check out of sync count - this is the number
- # of changes that would have occurred in
- # non-noop mode.
- expected_out_of_sync_count = 0
- if (machine_state != nil) != file_would_be_there_if_not_noop
- expected_out_of_sync_count = 1
- elsif machine_state != nil
- if mode_property != nil && mode_property != machine_state
- expected_out_of_sync_count = 1
- end
- end
- if !noop_mode
- expected_out_of_sync_count.should == expected_change_count
- end
- status.out_of_sync_count.should == expected_out_of_sync_count
-
- # Check legacy summary fields
- status.changed.should == (expected_change_count != 0)
- status.out_of_sync.should == (expected_out_of_sync_count != 0)
-
- # Check the :synced field on state.yml
- synced_should_be_set = !noop_mode && status.changed
- (@harness.cached(resource, :synced) != nil).should == synced_should_be_set
- end; end
- end
- end
- end
- end
- end; end
- end
- end; end
- end; end
-
it "should not apply changes if allow_changes?() returns false" do
test_file = tmpfile('foo')
resource = Puppet::Type.type(:file).new :path => test_file, :backup => false, :ensure => :file
resource.expects(:err).never # make sure no exceptions get swallowed
@harness.expects(:allow_changes?).with(resource).returns false
status = @harness.evaluate(resource)
- File.exists?(test_file).should == false
+ Puppet::FileSystem::File.exist?(test_file).should == false
end
end
diff --git a/spec/unit/transaction_spec.rb b/spec/unit/transaction_spec.rb
index 840b34c15..04ce08c4f 100755
--- a/spec/unit/transaction_spec.rb
+++ b/spec/unit/transaction_spec.rb
@@ -308,7 +308,7 @@ describe Puppet::Transaction do
transaction.evaluate
generated.each do |res|
- res.must be_tagged(generator.tags)
+ res.must be_tagged(*generator.tags)
end
end
end
@@ -404,7 +404,6 @@ describe Puppet::Transaction do
it "should otherwise let the resource determine if it is missing tags" do
tags = ['one', 'two']
@transaction.tags = tags
- @resource.expects(:tagged?).with(*tags).returns(false)
@transaction.should be_missing_tags(@resource)
end
end
@@ -478,6 +477,48 @@ describe Puppet::Transaction do
end
end
+ describe "during teardown" do
+ before :each do
+ @catalog = Puppet::Resource::Catalog.new
+ @transaction = Puppet::Transaction.new(@catalog, nil, Puppet::Graph::RandomPrioritizer.new)
+ end
+
+ it "should call ::post_resource_eval on provider classes that support it" do
+ @resource = Puppet::Type.type(:notify).new :title => "foo"
+ @catalog.add_resource @resource
+
+ # 'expects' will cause 'respond_to?(:post_resource_eval)' to return true
+ @resource.provider.class.expects(:post_resource_eval)
+ @transaction.evaluate
+ end
+
+ it "should call ::post_resource_eval even if other providers' ::post_resource_eval fails" do
+ @resource3 = Puppet::Type.type(:user).new :title => "bloo"
+ @resource3.provider.class.stubs(:post_resource_eval).raises
+ @resource4 = Puppet::Type.type(:notify).new :title => "blob"
+ @resource4.provider.class.stubs(:post_resource_eval).raises
+ @catalog.add_resource @resource3
+ @catalog.add_resource @resource4
+
+ # ruby's Set does not guarantee ordering, so both resource3 and resource4
+ # need to expect post_resource_eval, rather than just the 'first' one.
+ @resource3.provider.class.expects(:post_resource_eval)
+ @resource4.provider.class.expects(:post_resource_eval)
+
+ @transaction.evaluate
+ end
+
+ it "should call ::post_resource_eval even if one of the resources fails" do
+ @resource3 = Puppet::Type.type(:notify).new :title => "bloo"
+ @resource3.stubs(:retrieve_resource).raises
+ @catalog.add_resource @resource3
+
+ @resource3.provider.class.expects(:post_resource_eval)
+
+ @transaction.evaluate
+ end
+ end
+
describe 'when checking application run state' do
before do
@catalog = Puppet::Resource::Catalog.new
@@ -594,32 +635,37 @@ describe Puppet::Transaction, " when determining tags" do
it "should default to the tags specified in the :tags setting" do
Puppet[:tags] = "one"
- @transaction.tags.should == %w{one}
+ @transaction.should be_tagged("one")
end
it "should split tags based on ','" do
Puppet[:tags] = "one,two"
- @transaction.tags.should == %w{one two}
+ @transaction.should be_tagged("one")
+ @transaction.should be_tagged("two")
end
it "should use any tags set after creation" do
Puppet[:tags] = ""
@transaction.tags = %w{one two}
- @transaction.tags.should == %w{one two}
+ @transaction.should be_tagged("one")
+ @transaction.should be_tagged("two")
end
it "should always convert assigned tags to an array" do
@transaction.tags = "one::two"
- @transaction.tags.should == %w{one::two}
+ @transaction.should be_tagged("one::two")
end
it "should accept a comma-delimited string" do
@transaction.tags = "one, two"
- @transaction.tags.should == %w{one two}
+ @transaction.should be_tagged("one")
+ @transaction.should be_tagged("two")
end
it "should accept an empty string" do
+ @transaction.tags = "one, two"
+ @transaction.should be_tagged("one")
@transaction.tags = ""
- @transaction.tags.should == []
+ @transaction.should_not be_tagged("one")
end
end
diff --git a/spec/unit/type/component_spec.rb b/spec/unit/type/component_spec.rb
index 82c822dea..f3326a161 100755
--- a/spec/unit/type/component_spec.rb
+++ b/spec/unit/type/component_spec.rb
@@ -42,8 +42,8 @@ describe component do
component.new(:name => "Class[foo]").pathbuilder.must == ["Foo"]
end
- it "should produce an empty string if the component models the 'main' class" do
- component.new(:name => "Class[main]").pathbuilder.must == [""]
+ it "should produce the class name even for the class named main" do
+ component.new(:name => "Class[main]").pathbuilder.must == ["Main"]
end
it "should produce a resource reference if the component does not model a class" do
diff --git a/spec/unit/type/exec_spec.rb b/spec/unit/type/exec_spec.rb
index 85a5809dc..6d780b3ff 100755
--- a/spec/unit/type/exec_spec.rb
+++ b/spec/unit/type/exec_spec.rb
@@ -8,6 +8,8 @@ describe Puppet::Type.type(:exec) do
Puppet.features.stubs(:root?).returns(true)
output = rest.delete(:output) || ''
+
+ output = Puppet::Util::Execution::ProcessOutput.new(output, exitstatus)
tries = rest[:tries] || 1
args = {
@@ -21,14 +23,12 @@ describe Puppet::Type.type(:exec) do
exec = Puppet::Type.type(:exec).new(args)
status = stub "process", :exitstatus => exitstatus
- Puppet::Util::SUIDManager.expects(:run_and_capture).times(tries).
+ Puppet::Util::Execution.expects(:execute).times(tries).
with() { |*args|
args[0] == command &&
- args[1] == nil &&
- args[2] == nil &&
- args[3][:override_locale] == false &&
- args[3].has_key?(:custom_environment)
- } .returns([output, status])
+ args[1][:override_locale] == false &&
+ args[1].has_key?(:custom_environment)
+ }.returns(output)
return exec
end
@@ -61,7 +61,7 @@ describe Puppet::Type.type(:exec) do
end
describe "when execing" do
- it "should use the 'run_and_capture' method to exec" do
+ it "should use the 'execute' method to exec" do
exec_tester("true").refresh.should == :executed_command
end
@@ -753,4 +753,11 @@ describe Puppet::Type.type(:exec) do
type.new(:command => abs, :path => path).must be
end
end
+ describe "when providing a umask" do
+ it "should fail if an invalid umask is used" do
+ resource = Puppet::Type.type(:exec).new :command => @command
+ expect { resource[:umask] = '0028'}.to raise_error(Puppet::ResourceError, /umask specification is invalid/)
+ expect { resource[:umask] = '28' }.to raise_error(Puppet::ResourceError, /umask specification is invalid/)
+ end
+ end
end
diff --git a/spec/unit/type/file/content_spec.rb b/spec/unit/type/file/content_spec.rb
index c1c97a452..5a73dceb1 100755
--- a/spec/unit/type/file/content_spec.rb
+++ b/spec/unit/type/file/content_spec.rb
@@ -84,6 +84,13 @@ describe content do
@content.should.must == string
end
+
+ it "should convert the value to ASCII-8BIT", :if => "".respond_to?(:encode) do
+ @content = content.new(:resource => @resource)
+ @content.should= "Let's make a \u{2603}"
+
+ @content.actual_content.should == "Let's make a \xE2\x98\x83".force_encoding(Encoding::ASCII_8BIT)
+ end
end
describe "when retrieving the current content" do
@@ -329,8 +336,10 @@ describe content do
end
it "should copy content from the source to the file" do
+ dest_file = Puppet::FileSystem::File.new(@filename)
@resource.write(@source)
- IO.binread(@filename).should == @source_content
+
+ dest_file.binread.should == @source_content
end
it "should return the checksum computed" do
@@ -358,8 +367,10 @@ describe content do
end
it "should write the contents to the file" do
+ dest_file = Puppet::FileSystem::File.new(@filename)
@resource.write(@source)
- IO.binread(@filename).should == @source_content
+
+ dest_file.binread.should == @source_content
end
it "should not write anything if source is not found" do
diff --git a/spec/unit/type/file/ctime_spec.rb b/spec/unit/type/file/ctime_spec.rb
index ba46da286..eea0f1f92 100755
--- a/spec/unit/type/file/ctime_spec.rb
+++ b/spec/unit/type/file/ctime_spec.rb
@@ -16,7 +16,7 @@ describe Puppet::Type.type(:file).attrclass(:ctime) do
@resource[:audit] = [:ctime]
# this .to_resource audit behavior is magical :-(
- @resource.to_resource[:ctime].should == File.stat(@filename).ctime
+ @resource.to_resource[:ctime].should == Puppet::FileSystem::File.new(@filename).stat.ctime
end
it "should return absent if auditing an absent file" do
diff --git a/spec/unit/type/file/mode_spec.rb b/spec/unit/type/file/mode_spec.rb
index dc43ae498..8663fe57d 100755
--- a/spec/unit/type/file/mode_spec.rb
+++ b/spec/unit/type/file/mode_spec.rb
@@ -18,6 +18,10 @@ describe Puppet::Type.type(:file).attrclass(:mode) do
expect { mode.value = '0755' }.not_to raise_error
end
+ it "should accept valid symbolic strings" do
+ expect { mode.value = 'g+w,u-x' }.not_to raise_error
+ end
+
it "should not accept strings other than octal numbers" do
expect do
mode.value = 'readable please!'
@@ -35,6 +39,10 @@ describe Puppet::Type.type(:file).attrclass(:mode) do
mode.munge('0644').should == '644'
end
+ it "should accept symbolic strings as arguments and return them intact" do
+ mode.munge('u=rw,go=r').should == 'u=rw,go=r'
+ end
+
it "should accept integers are arguments" do
mode.munge(0644).should == '644'
end
@@ -72,11 +80,34 @@ describe Puppet::Type.type(:file).attrclass(:mode) do
mode.must_not be_insync('755')
end
- it "should return true if the file is a link and we are managing links", :unless => Puppet.features.microsoft_windows? do
- File.symlink('anything', path)
+ it "should return true if the file is a link and we are managing links", :if => Puppet.features.manages_symlinks? do
+ Puppet::FileSystem::File.new('anything').symlink(path)
mode.must be_insync('644')
end
+
+ describe "with a symbolic mode" do
+ let(:resource_sym) { Puppet::Type.type(:file).new :path => path, :mode => 'u+w,g-w' }
+ let(:mode_sym) { resource_sym.property(:mode) }
+
+ it "should return true if the mode matches, regardless of other bits" do
+ FileUtils.touch(path)
+
+ mode_sym.must be_insync('644')
+ end
+
+ it "should return false if the mode requires 0's where there are 1's" do
+ FileUtils.touch(path)
+
+ mode_sym.must_not be_insync('624')
+ end
+
+ it "should return false if the mode requires 1's where there are 0's" do
+ FileUtils.touch(path)
+
+ mode_sym.must_not be_insync('044')
+ end
+ end
end
describe "#retrieve" do
@@ -145,4 +176,19 @@ describe Puppet::Type.type(:file).attrclass(:mode) do
end
end
end
+
+ describe "#sync with a symbolic mode" do
+ let(:resource_sym) { Puppet::Type.type(:file).new :path => path, :mode => 'u+w,g-w' }
+ let(:mode_sym) { resource_sym.property(:mode) }
+
+ before { FileUtils.touch(path) }
+
+ it "changes only the requested bits" do
+ # lower nibble must be set to 4 for the sake of passing on Windows
+ FileUtils.chmod 0464, path
+ mode_sym.sync
+ file = Puppet::FileSystem::File.new(path)
+ (file.stat.mode & 0777).to_s(8).should == "644"
+ end
+ end
end
diff --git a/spec/unit/type/file/mtime_spec.rb b/spec/unit/type/file/mtime_spec.rb
index 93abcb2fe..a20bdf196 100755
--- a/spec/unit/type/file/mtime_spec.rb
+++ b/spec/unit/type/file/mtime_spec.rb
@@ -16,7 +16,7 @@ describe Puppet::Type.type(:file).attrclass(:mtime) do
@resource[:audit] = [:mtime]
# this .to_resource audit behavior is magical :-(
- @resource.to_resource[:mtime].should == File.stat(@filename).mtime
+ @resource.to_resource[:mtime].should == Puppet::FileSystem::File.new(@filename).stat.mtime
end
it "should return absent if auditing an absent file" do
diff --git a/spec/unit/type/file/source_spec.rb b/spec/unit/type/file/source_spec.rb
index 36cad8849..e645842c0 100755
--- a/spec/unit/type/file/source_spec.rb
+++ b/spec/unit/type/file/source_spec.rb
@@ -154,11 +154,10 @@ describe Puppet::Type.type(:file).attrclass(:source) do
describe "when copying the source values" do
before 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", :source => @foobar
+ @metadata = stub 'metadata', :owner => 100, :group => 200, :mode => "173", :checksum => "{md5}asdfasdf", :ftype => "file", :source => @foobar
@source.stubs(:metadata).returns @metadata
Puppet.features.stubs(:root?).returns true
@@ -202,7 +201,7 @@ describe Puppet::Type.type(:file).attrclass(:source) do
@resource[:content].must == @metadata.checksum
end
- it "should not copy the metadata's owner to the resource if it is already set" do
+ it "should not copy the metadata's owner, group, checksum and mode to the resource if they are already set" do
@resource[:owner] = 1
@resource[:group] = 2
@resource[:mode] = 3
@@ -217,26 +216,153 @@ describe Puppet::Type.type(:file).attrclass(:source) do
end
describe "and puppet is not running as root" do
- it "should not try to set the owner" do
- Puppet.features.expects(:root?).returns false
+ before do
+ Puppet.features.stubs(:root?).returns false
+ end
+ it "should not try to set the owner" do
@source.copy_source_values
@resource[:owner].should be_nil
end
+
+ it "should not try to set the group" do
+ @source.copy_source_values
+ @resource[:group].should be_nil
+ end
+ end
+
+ context "when source_permissions is `use_when_creating`" do
+ before :each do
+ @resource[:source_permissions] = "use_when_creating"
+ Puppet.features.expects(:root?).returns true
+ @source.stubs(:local?).returns(false)
+ end
+
+ context "when managing a new file" do
+ 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
+ @resource[:mode].must == "173"
+ end
+
+ it "copies the remote owner" do
+ @source.copy_source_values
+
+ @resource[:owner].must == 100
+ end
+
+ it "copies the remote group" do
+ @source.copy_source_values
+
+ @resource[:group].must == 200
+ end
+
+ it "copies the remote mode" do
+ @source.copy_source_values
+
+ @resource[:mode].must == "173"
+ end
+ end
+
+ context "when managing an existing file" do
+ before :each do
+ Puppet::FileSystem::File.stubs(:exist?).with(@resource[:path]).returns(true)
+ end
+
+ it "should not copy owner, group or mode from local sources" do
+ @source.stubs(:local?).returns true
+
+ @source.copy_source_values
+
+ @resource[:owner].must be_nil
+ @resource[:group].must be_nil
+ @resource[:mode].must be_nil
+ end
+
+ it "preserves the local owner" do
+ @source.copy_source_values
+
+ @resource[:owner].must be_nil
+ end
+
+ it "preserves the local group" do
+ @source.copy_source_values
+
+ @resource[:group].must be_nil
+ end
+
+ it "preserves the local mode" do
+ @source.copy_source_values
+
+ @resource[:mode].must be_nil
+ end
+ end
+ end
+
+ context "when source_permissions is `ignore`" do
+ before :each do
+ @resource[:source_permissions] = "ignore"
+ @source.stubs(:local?).returns(false)
+ Puppet.features.expects(:root?).returns true
+ end
+
+ it "should not copy owner, group or mode from local sources" do
+ @source.stubs(:local?).returns true
+
+ @source.copy_source_values
+
+ @resource[:owner].must be_nil
+ @resource[:group].must be_nil
+ @resource[:mode].must be_nil
+ end
+
+ it "preserves the local owner" do
+ @source.copy_source_values
+
+ @resource[:owner].must be_nil
+ end
+
+ it "preserves the local group" do
+ @source.copy_source_values
+
+ @resource[:group].must be_nil
+ end
+
+ it "preserves the local mode" do
+ @source.copy_source_values
+
+ @resource[:mode].must be_nil
+ end
end
describe "on Windows" do
before :each do
Puppet.features.stubs(:microsoft_windows?).returns true
end
+ let(:deprecation_message) { "Copying owner/mode/group from the" <<
+ " source file on Windows is deprecated;" <<
+ " use source_permissions => ignore." }
- it "should not copy owner and group from remote sources" do
+ it "should copy only mode from remote sources" do
@source.stubs(:local?).returns false
@source.copy_source_values
@resource[:owner].must be_nil
@resource[:group].must be_nil
+ @resource[:mode].must == "173"
+ end
+
+ it "should copy mode from remote sources" do
+ @source.stubs(:local?).returns false
+
+ @source.copy_source_values
+
+ @resource[:mode].must == "173"
end
it "should copy owner and group from local sources" do
@@ -246,6 +372,51 @@ describe Puppet::Type.type(:file).attrclass(:source) do
@resource[:owner].must == 100
@resource[:group].must == 200
+ @resource[:mode].must == "173"
+ end
+
+ it "should issue deprecation warning when copying metadata from remote sources when group, owner, and mode are unspecified" do
+ @source.stubs(:local?).returns false
+ Puppet.expects(:deprecation_warning).with(deprecation_message).at_least_once
+
+ @source.copy_source_values
+ end
+
+ it "should issue deprecation warning when copying metadata from remote sources if only user is unspecified" do
+ @source.stubs(:local?).returns false
+ Puppet.expects(:deprecation_warning).with(deprecation_message).at_least_once
+ @resource[:group] = 2
+ @resource[:mode] = 3
+
+ @source.copy_source_values
+ end
+
+ it "should issue deprecation warning when copying metadata from remote sources if only group is unspecified" do
+ @source.stubs(:local?).returns false
+ Puppet.expects(:deprecation_warning).with(deprecation_message).at_least_once
+ @resource[:owner] = 1
+ @resource[:mode] = 3
+
+ @source.copy_source_values
+ end
+
+ it "should issue deprecation warning when copying metadata from remote sources if only mode is unspecified" do
+ @source.stubs(:local?).returns false
+ Puppet.expects(:deprecation_warning).with(deprecation_message).at_least_once
+ @resource[:owner] = 1
+ @resource[:group] = 2
+
+ @source.copy_source_values
+ end
+
+ it "should not issue deprecation warning when copying metadata from remote sources if group, owner, and mode are all specified" do
+ @source.stubs(:local?).returns false
+ Puppet.expects(:deprecation_warning).with(deprecation_message).never
+ @resource[:owner] = 1
+ @resource[:group] = 2
+ @resource[:mode] = 3
+
+ @source.copy_source_values
end
end
end
@@ -358,5 +529,4 @@ describe Puppet::Type.type(:file).attrclass(:source) do
end
end
end
-
end
diff --git a/spec/unit/type/file_spec.rb b/spec/unit/type/file_spec.rb
index dd695eeda..75b58926a 100755
--- a/spec/unit/type/file_spec.rb
+++ b/spec/unit/type/file_spec.rb
@@ -10,7 +10,6 @@ describe Puppet::Type.type(:file) do
let(:catalog) { Puppet::Resource::Catalog.new }
before do
- @real_posix = Puppet.features.posix?
Puppet.features.stubs("posix?").returns(true)
end
@@ -78,33 +77,29 @@ describe Puppet::Type.type(:file) do
end
describe "when using UNC filenames", :if => Puppet.features.microsoft_windows? do
- before :each do
- pending("UNC file paths not yet supported")
- end
-
it "should remove trailing slashes" do
- file[:path] = "//server/foo/bar/baz/"
- file[:path].should == "//server/foo/bar/baz"
+ file[:path] = "//localhost/foo/bar/baz/"
+ file[:path].should == "//localhost/foo/bar/baz"
end
it "should remove double slashes" do
- file[:path] = "//server/foo/bar//baz"
- file[:path].should == "//server/foo/bar/baz"
+ file[:path] = "//localhost/foo/bar//baz"
+ file[:path].should == "//localhost/foo/bar/baz"
end
it "should remove trailing double slashes" do
- file[:path] = "//server/foo/bar/baz//"
- file[:path].should == "//server/foo/bar/baz"
+ file[:path] = "//localhost/foo/bar/baz//"
+ file[:path].should == "//localhost/foo/bar/baz"
end
it "should remove a trailing slash from a sharename" do
- file[:path] = "//server/foo/"
- file[:path].should == "//server/foo"
+ file[:path] = "//localhost/foo/"
+ file[:path].should == "//localhost/foo"
end
it "should not modify a sharename" do
- file[:path] = "//server/foo"
- file[:path].should == "//server/foo"
+ file[:path] = "//localhost/foo"
+ file[:path].should == "//localhost/foo"
end
end
end
@@ -352,7 +347,7 @@ describe Puppet::Type.type(:file) do
file[:ensure].should == :file
end
- it "should set a desired 'ensure' value if none is set and 'target' is set" do
+ it "should set a desired 'ensure' value if none is set and 'target' is set", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
file = described_class.new(:path => path, :target => File.expand_path(__FILE__))
file[:ensure].should == :link
end
@@ -397,7 +392,7 @@ describe Puppet::Type.type(:file) do
:target => "some_target",
:source => File.expand_path("some_source"),
}.each do |param, value|
- it "should omit the #{param} parameter" do
+ it "should omit the #{param} parameter", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
# Make a new file, because we have to set the param at initialization
# or it wouldn't be copied regardless.
file = described_class.new(:path => path, param => value)
@@ -603,7 +598,7 @@ describe Puppet::Type.type(:file) do
file.recurse_link("first" => @resource)
end
- it "should set the target to the full path of discovered file and set :ensure to :link if the file is not a directory" do
+ it "should set the target to the full path of discovered file and set :ensure to :link if the file is not a directory", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
file.stubs(:perform_recursion).returns [@first, @second]
file.recurse_link("first" => @resource, "second" => file)
@@ -925,20 +920,20 @@ describe Puppet::Type.type(:file) do
file.remove_existing(:directory).should == true
- File.exists?(file[:path]).should == false
+ Puppet::FileSystem::File.exist?(file[:path]).should == false
end
- it "should remove an existing link", :unless => Puppet.features.microsoft_windows? do
+ it "should remove an existing link", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
file.stubs(:perform_backup).returns true
target = tmpfile('link_target')
FileUtils.touch(target)
- FileUtils.symlink(target, path)
+ Puppet::FileSystem::File.new(target).symlink(path)
file[:target] = target
file.remove_existing(:directory).should == true
- File.exists?(file[:path]).should == false
+ Puppet::FileSystem::File.exist?(file[:path]).should == false
end
it "should fail if the file is not a file, link, or directory" do
@@ -952,7 +947,7 @@ describe Puppet::Type.type(:file) do
file.stat
file.stubs(:stat).returns stub('stat', :ftype => 'file')
- File.stubs(:unlink)
+ Puppet::FileSystem::File.stubs(:unlink)
file.remove_existing(:directory).should == true
file.instance_variable_get(:@stat).should == :needs_stat
@@ -1010,11 +1005,11 @@ describe Puppet::Type.type(:file) do
end
end
- describe "#stat", :unless => Puppet.features.microsoft_windows? do
+ describe "#stat", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
before do
target = tmpfile('link_target')
FileUtils.touch(target)
- FileUtils.symlink(target, path)
+ Puppet::FileSystem::File.new(target).symlink(path)
file[:target] = target
file[:links] = :manage # so we always use :lstat
@@ -1033,7 +1028,7 @@ describe Puppet::Type.type(:file) do
end
it "should return nil if the file does not exist" do
- file[:path] = '/foo/bar/baz/non-existent'
+ file[:path] = make_absolute('/foo/bar/baz/non-existent')
file.stat.should be_nil
end
@@ -1207,7 +1202,7 @@ describe Puppet::Type.type(:file) do
describe "when autorequiring" do
describe "target" do
- it "should require file resource when specified with the target property" do
+ it "should require file resource when specified with the target property", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
file = described_class.new(:path => File.expand_path("/foo"), :ensure => :directory)
link = described_class.new(:path => File.expand_path("/bar"), :ensure => :link, :target => File.expand_path("/foo"))
catalog.add_resource file
@@ -1229,7 +1224,7 @@ describe Puppet::Type.type(:file) do
reqs[0].target.must == link
end
- it "should not require target if target is not managed" do
+ it "should not require target if target is not managed", :if => described_class.defaultprovider.feature?(:manages_symlinks) do
link = described_class.new(:path => File.expand_path('/foo'), :ensure => :link, :target => '/bar')
catalog.add_resource link
link.autorequire.size.should == 0
@@ -1272,8 +1267,8 @@ describe Puppet::Type.type(:file) do
describe "on Windows systems", :if => Puppet.features.microsoft_windows? do
describe "when using UNC filenames" do
it "should autorequire its parent directory" do
- file[:path] = '//server/foo/bar/baz'
- dir = described_class.new(:path => "//server/foo/bar")
+ file[:path] = '//localhost/foo/bar/baz'
+ dir = described_class.new(:path => "//localhost/foo/bar")
catalog.add_resource file
catalog.add_resource dir
reqs = file.autorequire
@@ -1282,9 +1277,9 @@ describe Puppet::Type.type(:file) do
end
it "should autorequire its nearest ancestor directory" do
- file = described_class.new(:path => "//server/foo/bar/baz/qux")
- dir = described_class.new(:path => "//server/foo/bar/baz")
- grandparent = described_class.new(:path => "//server/foo/bar")
+ file = described_class.new(:path => "//localhost/foo/bar/baz/qux")
+ dir = described_class.new(:path => "//localhost/foo/bar/baz")
+ grandparent = described_class.new(:path => "//localhost/foo/bar")
catalog.add_resource file
catalog.add_resource dir
catalog.add_resource grandparent
@@ -1295,13 +1290,13 @@ describe Puppet::Type.type(:file) do
end
it "should not autorequire anything when there is no nearest ancestor directory" do
- file = described_class.new(:path => "//server/foo/bar/baz/qux")
+ file = described_class.new(:path => "//localhost/foo/bar/baz/qux")
catalog.add_resource file
file.autorequire.should be_empty
end
it "should not autorequire its parent dir if its parent dir is itself" do
- file = described_class.new(:path => "//server/foo")
+ file = described_class.new(:path => "//localhost/foo")
catalog.add_resource file
puts file.autorequire
file.autorequire.should be_empty
@@ -1311,49 +1306,46 @@ describe Puppet::Type.type(:file) do
end
end
- describe "when managing links" do
+ describe "when managing links", :if => Puppet.features.manages_symlinks? do
require 'tempfile'
- if @real_posix
- describe "on POSIX systems" do
- before do
- Dir.mkdir(path)
- @target = File.join(path, "target")
- @link = File.join(path, "link")
-
- File.open(@target, "w", 0644) { |f| f.puts "yayness" }
- File.symlink(@target, @link)
-
- file[:path] = @link
- file[:mode] = 0755
-
- catalog.add_resource file
- end
+ before :each do
+ Dir.mkdir(path)
+ @target = File.join(path, "target")
+ @link = File.join(path, "link")
+
+ target = described_class.new(
+ :ensure => :file, :path => @target,
+ :catalog => catalog, :content => 'yayness',
+ :mode => 0644)
+ catalog.add_resource target
+
+ @link_resource = described_class.new(
+ :ensure => :link, :path => @link,
+ :target => @target, :catalog => catalog,
+ :mode => 0755)
+ catalog.add_resource @link_resource
- it "should default to managing the link" do
- catalog.apply
- # I convert them to strings so they display correctly if there's an error.
- (File.stat(@target).mode & 007777).to_s(8).should == '644'
- end
+ # to prevent the catalog from trying to write state.yaml
+ Puppet::Util::Storage.stubs(:store)
+ end
- it "should be able to follow links" do
- file[:links] = :follow
- catalog.apply
+ it "should preserve the original file mode and ignore the one set by the link" do
+ @link_resource[:links] = :manage # default
+ catalog.apply
- (File.stat(@target).mode & 007777).to_s(8).should == '755'
- end
- end
- else # @real_posix
- # should recode tests using expectations instead of using the filesystem
+ # I convert them to strings so they display correctly if there's an error.
+ (Puppet::FileSystem::File.new(@target).stat.mode & 007777).to_s(8).should == '644'
end
- describe "on Microsoft Windows systems" do
- before do
- Puppet.features.stubs(:posix?).returns(false)
- Puppet.features.stubs(:microsoft_windows?).returns(true)
- end
+ it "should manage the mode of the followed link" do
+ pending("Windows cannot presently manage the mode when following symlinks",
+ :if => Puppet.features.microsoft_windows?) do
+ @link_resource[:links] = :follow
+ catalog.apply
- it "should refuse to work with links"
+ (Puppet::FileSystem::File.new(@target).stat.mode & 007777).to_s(8).should == '755'
+ end
end
end
@@ -1436,7 +1428,7 @@ describe Puppet::Type.type(:file) do
catalog.apply
- File.should be_exist(path)
+ Puppet::FileSystem::File.exist?(path).should be_true
@logs.should_not be_any {|l| l.level != :notice }
end
end
diff --git a/spec/unit/type/group_spec.rb b/spec/unit/type/group_spec.rb
index f8d24f0df..55f6e548b 100755
--- a/spec/unit/type/group_spec.rb
+++ b/spec/unit/type/group_spec.rb
@@ -61,4 +61,24 @@ describe Puppet::Type.type(:group) do
type.exists?.should == true
end
+
+ describe "should delegate :members implementation to the provider:" do
+
+ let (:provider) { @class.provide(:testing) { has_features :manages_members } }
+ let (:provider_instance) { provider.new }
+ let (:type) { @class.new(:name => "group", :provider => provider_instance, :members => ['user1']) }
+
+ it "insync? calls members_insync?" do
+ provider_instance.expects(:members_insync?).with(['user1'], ['user1']).returns true
+ type.property(:members).insync?(['user1']).should be_true
+ end
+
+ it "is_to_s and should_to_s call members_to_s" do
+ provider_instance.expects(:members_to_s).with(['user2', 'user1']).returns "user2 (), user1 ()"
+ provider_instance.expects(:members_to_s).with(['user1']).returns "user1 ()"
+
+ type.property(:members).is_to_s('user1').should == 'user1 ()'
+ type.property(:members).should_to_s('user2,user1').should == 'user2 (), user1 ()'
+ end
+ end
end
diff --git a/spec/unit/type/k5login_spec.rb b/spec/unit/type/k5login_spec.rb
index 2524d98c5..484ddf8e7 100755
--- a/spec/unit/type/k5login_spec.rb
+++ b/spec/unit/type/k5login_spec.rb
@@ -46,7 +46,7 @@ describe Puppet::Type.type(:k5login), :unless => Puppet.features.microsoft_windo
it "should create the file when synced" do
resource(:ensure => 'present').parameter(:ensure).sync
- File.should be_exist path
+ Puppet::FileSystem::File.exist?(path).should be_true
end
end
@@ -83,7 +83,7 @@ describe Puppet::Type.type(:k5login), :unless => Puppet.features.microsoft_windo
it "should remove the file ensure is absent" do
resource(:ensure => 'absent').property(:ensure).sync
- File.should_not be_exist path
+ Puppet::FileSystem::File.exist?(path).should be_false
end
it "should write one principal to the file" do
@@ -106,7 +106,7 @@ describe Puppet::Type.type(:k5login), :unless => Puppet.features.microsoft_windo
it "should update the mode to #{mode}" do
resource(:mode => mode).property(:mode).sync
- (File.stat(path).mode & 07777).to_s(8).should == mode
+ (Puppet::FileSystem::File.new(path).stat.mode & 07777).to_s(8).should == mode
end
end
end
diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb
index 726577891..75b2f505d 100755
--- a/spec/unit/type/mount_spec.rb
+++ b/spec/unit/type/mount_spec.rb
@@ -536,4 +536,57 @@ describe Puppet::Type.type(:mount), :unless => Puppet.features.microsoft_windows
run_in_catalog(resource)
end
end
+
+ describe "establishing autorequires" do
+
+ def create_resource(path)
+ described_class.new(
+ :name => path,
+ :provider => providerclass.new(path)
+ )
+ end
+
+ def create_catalog(*resources)
+ catalog = Puppet::Resource::Catalog.new
+ resources.each do |resource|
+ catalog.add_resource resource
+ end
+
+ catalog
+ end
+
+ let(:root_mount) { create_resource("/") }
+ let(:var_mount) { create_resource("/var") }
+ let(:log_mount) { create_resource("/var/log") }
+
+ before do
+ create_catalog(root_mount, var_mount, log_mount)
+ end
+
+ it "adds no autorequires for the root mount" do
+ expect(root_mount.autorequire).to be_empty
+ end
+
+ it "adds the parent autorequire for a mount with one parent" do
+ parent_relationship = var_mount.autorequire[0]
+
+ expect(var_mount.autorequire).to have_exactly(1).item
+
+ expect(parent_relationship.source).to eq root_mount
+ expect(parent_relationship.target).to eq var_mount
+ end
+
+ it "adds both parent autorequires for a mount with two parents" do
+ grandparent_relationship = log_mount.autorequire[0]
+ parent_relationship = log_mount.autorequire[1]
+
+ expect(log_mount.autorequire).to have_exactly(2).items
+
+ expect(grandparent_relationship.source).to eq root_mount
+ expect(grandparent_relationship.target).to eq log_mount
+
+ expect(parent_relationship.source).to eq var_mount
+ expect(parent_relationship.target).to eq log_mount
+ end
+ end
end
diff --git a/spec/unit/type/nagios_spec.rb b/spec/unit/type/nagios_spec.rb
index 8c86aae7f..84d4338de 100755
--- a/spec/unit/type/nagios_spec.rb
+++ b/spec/unit/type/nagios_spec.rb
@@ -3,6 +3,222 @@ require 'spec_helper'
require 'puppet/external/nagios'
+describe "Nagios parser" do
+
+ NONESCAPED_SEMICOLON_COMMENT = <<-'EOL'
+define host{
+ use linux-server ; Name of host template to use
+ host_name localhost
+ alias localhost
+ address 127.0.0.1
+ }
+
+define command{
+ command_name notify-host-by-email
+ command_line /usr/bin/printf "%b" "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | /usr/bin/mail -s "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" $CONTACTEMAIL$
+ }
+EOL
+
+ LINE_COMMENT_SNIPPET = <<-'EOL'
+
+# This is a comment starting at the beginning of a line
+
+define command{
+
+# This is a comment starting at the beginning of a line
+
+ command_name command_name
+
+# This is a comment starting at the beginning of a line
+ ## --PUPPET_NAME-- (called '_naginator_name' in the manifest) command_name
+
+ command_line command_line
+
+# This is a comment starting at the beginning of a line
+
+ }
+
+# This is a comment starting at the beginning of a line
+
+EOL
+
+ LINE_COMMENT_SNIPPET2 = <<-'EOL'
+ define host{
+ use linux-server ; Name of host template to use
+ host_name localhost
+ alias localhost
+ address 127.0.0.1
+ }
+define command{
+ command_name command_name2
+ command_line command_line2
+ }
+EOL
+
+ UNKNOWN_NAGIOS_OBJECT_DEFINITION = <<-'EOL'
+ define command2{
+ command_name notify-host-by-email
+ command_line /usr/bin/printf "%b" "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | /usr/bin/mail -s "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" $CONTACTEMAIL$
+ }
+ EOL
+
+ MISSING_CLOSING_CURLY_BRACKET = <<-'EOL'
+ define command{
+ command_name notify-host-by-email
+ command_line /usr/bin/printf "%b" "***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | /usr/bin/mail -s "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" $CONTACTEMAIL$
+ EOL
+
+ ESCAPED_SEMICOLON = <<-'EOL'
+ define command {
+ command_name nagios_table_size
+ command_line $USER3$/check_mysql_health --hostname localhost --username nagioschecks --password nagiosCheckPWD --mode sql --name "SELECT ROUND(Data_length/1024) as Data_kBytes from INFORMATION_SCHEMA.TABLES where TABLE_NAME=\"$ARG1$\"\;" --name2 "table size" --units kBytes -w $ARG2$ -c $ARG3$
+ }
+ EOL
+
+ POUND_SIGN_HASH_SYMBOL_NOT_IN_FIRST_COLUMN = <<-'EOL'
+ define command {
+ command_name notify-by-irc
+ command_line /usr/local/bin/riseup-nagios-client.pl "$HOSTNAME$ ($SERVICEDESC$) $NOTIFICATIONTYPE$ #$SERVICEATTEMPT$ $SERVICESTATETYPE$ $SERVICEEXECUTIONTIME$s $SERVICELATENCY$s $SERVICEOUTPUT$ $SERVICEPERFDATA$"
+ }
+ EOL
+
+ ANOTHER_ESCAPED_SEMICOLON = <<-EOL
+define command {
+\tcommand_line LC_ALL=en_US.UTF-8 /usr/lib/nagios/plugins/check_haproxy -u 'http://blah:blah@$HOSTADDRESS$:8080/haproxy?stats\\;csv'
+\tcommand_name check_haproxy
+}
+EOL
+
+ it "should parse without error" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(NONESCAPED_SEMICOLON_COMMENT)
+ }.to_not raise_error
+ end
+
+ describe "when parsing a statement" do
+ parser = Nagios::Parser.new
+ results = parser.parse(NONESCAPED_SEMICOLON_COMMENT)
+ results.each do |obj|
+ it "should have the proper base type" do
+ obj.should be_a_kind_of(Nagios::Base)
+ end
+ end
+ end
+
+ it "should raise an error when an incorrect object definition is present" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(UNKNOWN_NAGIOS_OBJECT_DEFINITION)
+ }.to raise_error Nagios::Base::UnknownNagiosType
+ end
+
+ it "should raise an error when syntax is not correct" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(MISSING_CLOSING_CURLY_BRACKET)
+ }.to raise_error Nagios::Parser::SyntaxError
+ end
+
+ describe "when encoutering ';'" do
+ it "should not throw an exception" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(ESCAPED_SEMICOLON)
+ }.to_not raise_error Nagios::Parser::SyntaxError
+ end
+
+ it "should ignore it if it is a comment" do
+ parser = Nagios::Parser.new
+ results = parser.parse(NONESCAPED_SEMICOLON_COMMENT)
+ results[0].use.should eql("linux-server")
+ end
+
+ it "should parse correctly if it is escaped" do
+ parser = Nagios::Parser.new
+ results = parser.parse(ESCAPED_SEMICOLON)
+ results[0].command_line.should eql("$USER3$/check_mysql_health --hostname localhost --username nagioschecks --password nagiosCheckPWD --mode sql --name \"SELECT ROUND(Data_length/1024) as Data_kBytes from INFORMATION_SCHEMA.TABLES where TABLE_NAME=\\\"$ARG1$\\\";\" --name2 \"table size\" --units kBytes -w $ARG2$ -c $ARG3$")
+ end
+ end
+
+ describe "when encountering '#'" do
+
+ it "should not throw an exception" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(POUND_SIGN_HASH_SYMBOL_NOT_IN_FIRST_COLUMN)
+ }.to_not raise_error Nagios::Parser::SyntaxError
+ end
+
+
+ it "should ignore it at the beginning of a line" do
+ parser = Nagios::Parser.new
+ results = parser.parse(LINE_COMMENT_SNIPPET)
+ results[0].command_line.should eql("command_line")
+ end
+
+ it "should let it go anywhere else" do
+ parser = Nagios::Parser.new
+ results = parser.parse(POUND_SIGN_HASH_SYMBOL_NOT_IN_FIRST_COLUMN)
+ results[0].command_line.should eql("/usr/local/bin/riseup-nagios-client.pl \"$HOSTNAME$ ($SERVICEDESC$) $NOTIFICATIONTYPE$ \#$SERVICEATTEMPT$ $SERVICESTATETYPE$ $SERVICEEXECUTIONTIME$s $SERVICELATENCY$s $SERVICEOUTPUT$ $SERVICEPERFDATA$\"")
+ end
+
+ end
+
+ describe "when encountering ';' again" do
+ it "should not throw an exception" do
+ parser = Nagios::Parser.new
+ expect {
+ results = parser.parse(ANOTHER_ESCAPED_SEMICOLON)
+ }.to_not raise_error Nagios::Parser::SyntaxError
+ end
+
+ it "should parse correctly" do
+ parser = Nagios::Parser.new
+ results = parser.parse(ANOTHER_ESCAPED_SEMICOLON)
+ results[0].command_line.should eql("LC_ALL=en_US.UTF-8 /usr/lib/nagios/plugins/check_haproxy -u 'http://blah:blah@$HOSTADDRESS$:8080/haproxy?stats;csv'")
+ end
+ end
+
+
+ it "should be idempotent" do
+ parser = Nagios::Parser.new
+ src = ANOTHER_ESCAPED_SEMICOLON.dup
+ results = parser.parse(src)
+ nagios_type = Nagios::Base.create(:command)
+ nagios_type.command_name = results[0].command_name
+ nagios_type.command_line = results[0].command_line
+ nagios_type.to_s.should eql(ANOTHER_ESCAPED_SEMICOLON)
+ end
+
+end
+
+describe "Nagios generator" do
+
+ it "should escape ';'" do
+ param = '$USER3$/check_mysql_health --hostname localhost --username nagioschecks --password nagiosCheckPWD --mode sql --name "SELECT ROUND(Data_length/1024) as Data_kBytes from INFORMATION_SCHEMA.TABLES where TABLE_NAME=\"$ARG1$\";" --name2 "table size" --units kBytes -w $ARG2$ -c $ARG3$'
+ nagios_type = Nagios::Base.create(:command)
+ nagios_type.command_line = param
+ nagios_type.to_s.should eql("define command {\n\tcommand_line $USER3$/check_mysql_health --hostname localhost --username nagioschecks --password nagiosCheckPWD --mode sql --name \"SELECT ROUND(Data_length/1024) as Data_kBytes from INFORMATION_SCHEMA.TABLES where TABLE_NAME=\\\"$ARG1$\\\"\\;\" --name2 \"table size\" --units kBytes -w $ARG2$ -c $ARG3$\n}\n")
+ end
+
+ it "should escape ';' if it is not already the case" do
+ param = "LC_ALL=en_US.UTF-8 /usr/lib/nagios/plugins/check_haproxy -u 'http://blah:blah@$HOSTADDRESS$:8080/haproxy?stats;csv'"
+ nagios_type = Nagios::Base.create(:command)
+ nagios_type.command_line = param
+ nagios_type.to_s.should eql("define command {\n\tcommand_line LC_ALL=en_US.UTF-8 /usr/lib/nagios/plugins/check_haproxy -u 'http://blah:blah@$HOSTADDRESS$:8080/haproxy?stats\\;csv'\n}\n")
+ end
+
+ it "should be idempotent" do
+ param = '$USER3$/check_mysql_health --hostname localhost --username nagioschecks --password nagiosCheckPWD --mode sql --name "SELECT ROUND(Data_length/1024) as Data_kBytes from INFORMATION_SCHEMA.TABLES where TABLE_NAME=\"$ARG1$\";" --name2 "table size" --units kBytes -w $ARG2$ -c $ARG3$'
+ nagios_type = Nagios::Base.create(:command)
+ nagios_type.command_line = param
+ parser = Nagios::Parser.new
+ results = parser.parse(nagios_type.to_s)
+ results[0].command_line.should eql(param)
+ end
+end
+
describe "Nagios resource types" do
Nagios::Base.eachtype do |name, nagios_type|
puppet_type = Puppet::Type.type("nagios_#{name}")
diff --git a/spec/unit/type/package_spec.rb b/spec/unit/type/package_spec.rb
index 5312b3f38..fefd15805 100755
--- a/spec/unit/type/package_spec.rb
+++ b/spec/unit/type/package_spec.rb
@@ -51,7 +51,7 @@ describe Puppet::Type.type(:package) do
:clear => nil,
:validate_source => nil
)
- Puppet::Type.type(:package).defaultprovider.expects(:new).returns(@provider)
+ Puppet::Type.type(:package).defaultprovider.stubs(:new).returns(@provider)
end
it "should support :present as a value to :ensure" do
@@ -100,6 +100,12 @@ describe Puppet::Type.type(:package) do
it "should accept any string as an argument to :source" do
expect { Puppet::Type.type(:package).new(:name => "yay", :source => "stuff") }.to_not raise_error
end
+
+ it "should not accept a non-string name" do
+ expect do
+ Puppet::Type.type(:package).new(:name => ["error"])
+ end.to raise_error(Puppet::ResourceError, /Name must be a String/)
+ end
end
module PackageEvaluationTesting
diff --git a/spec/unit/type/schedule_spec.rb b/spec/unit/type/schedule_spec.rb
index 020f7d841..0610bd175 100755
--- a/spec/unit/type/schedule_spec.rb
+++ b/spec/unit/type/schedule_spec.rb
@@ -62,6 +62,12 @@ describe Puppet::Type.type(:schedule) do
end
end
+ it "should not produce default schedules when default_schedules is false" do
+ Puppet[:default_schedules] = false
+ schedules = Puppet::Type.type(:schedule).mkdefaultschedules
+ schedules.must have_exactly(0).items
+ end
+
it "should produce a schedule named puppet with a period of hourly and a repeat of 2" do
schedules = Puppet::Type.type(:schedule).mkdefaultschedules
schedules.find { |s|
diff --git a/spec/unit/type/service_spec.rb b/spec/unit/type/service_spec.rb
index 630b44b75..e36d11a56 100755
--- a/spec/unit/type/service_spec.rb
+++ b/spec/unit/type/service_spec.rb
@@ -120,14 +120,14 @@ describe Puppet::Type.type(:service), "when validating attribute values" do
end
it "should split paths on '#{File::PATH_SEPARATOR}'" do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:directory?).returns(true)
svc = Puppet::Type.type(:service).new(:name => "yay", :path => "/one/two#{File::PATH_SEPARATOR}/three/four")
svc[:path].should == %w{/one/two /three/four}
end
it "should accept arrays of paths joined by '#{File::PATH_SEPARATOR}'" do
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
FileTest.stubs(:directory?).returns(true)
svc = Puppet::Type.type(:service).new(:name => "yay", :path => ["/one#{File::PATH_SEPARATOR}/two", "/three#{File::PATH_SEPARATOR}/four"])
svc[:path].should == %w{/one /two /three /four}
@@ -137,7 +137,7 @@ end
describe Puppet::Type.type(:service), "when setting default attribute values" do
it "should default to the provider's default path if one is available" do
FileTest.stubs(:directory?).returns(true)
- FileTest.stubs(:exist?).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).returns(true)
Puppet::Type.type(:service).defaultprovider.stubs(:respond_to?).returns(true)
Puppet::Type.type(:service).defaultprovider.stubs(:defpath).returns("testing")
diff --git a/spec/unit/type/tidy_spec.rb b/spec/unit/type/tidy_spec.rb
index cf3fc828b..abe5d26ff 100755
--- a/spec/unit/type/tidy_spec.rb
+++ b/spec/unit/type/tidy_spec.rb
@@ -10,17 +10,15 @@ describe tidy do
before do
@basepath = make_absolute("/what/ever")
Puppet.settings.stubs(:use)
-
- # for an unknown reason some of these specs fails when run individually
- # with a failed expectation on File.lstat in the autoloader.
- File.stubs(:lstat)
end
it "should use :lstat when stating a file" do
- resource = tidy.new :path => "/foo/bar", :age => "1d"
+ path = '/foo/bar'
+ resource = tidy.new :path => path, :age => "1d"
stat = mock 'stat'
- File.expects(:lstat).with("/foo/bar").returns stat
- resource.stat("/foo/bar").should == stat
+ stub_file = stub(path, :lstat => stat)
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
+ resource.stat(path).should == stat
end
[:age, :size, :path, :matches, :type, :recurse, :rmdirs].each do |param|
@@ -130,7 +128,8 @@ describe tidy do
before do
@tidy = Puppet::Type.type(:tidy).new :path => @basepath
@stat = stub 'stat', :ftype => "directory"
- File.stubs(:lstat).with(@basepath).returns @stat
+ @stub_file = stub(@basepath, :lstat => @stat)
+ Puppet::FileSystem::File.stubs(:new).with(@basepath).returns @stub_file
end
describe "and generating files" do
@@ -160,7 +159,7 @@ describe tidy do
end
it "should do nothing if the targeted file does not exist" do
- File.expects(:lstat).with(@basepath).raises Errno::ENOENT
+ @stub_file.expects(:lstat).raises Errno::ENOENT
@tidy.generate.should == []
end
@@ -311,32 +310,33 @@ describe tidy do
before do
@tidy = Puppet::Type.type(:tidy).new :path => @basepath
@stat = stub 'stat', :ftype => "file"
- File.stubs(:lstat).with(@basepath).returns @stat
+ @stub_file = stub(@basepath, :lstat => @stat)
+ Puppet::FileSystem::File.expects(:new).with(@basepath).returns @stub_file
end
it "should not try to recurse if the file does not exist" do
@tidy[:recurse] = true
- File.stubs(:lstat).with(@basepath).returns nil
+ @stub_file.stubs(:lstat).returns nil
@tidy.generate.should == []
end
it "should not be tidied if the file does not exist" do
- File.expects(:lstat).with(@basepath).raises Errno::ENOENT
+ @stub_file.expects(:lstat).raises Errno::ENOENT
@tidy.should_not be_tidy(@basepath)
end
it "should not be tidied if the user has no access to the file" do
- File.expects(:lstat).with(@basepath).raises Errno::EACCES
+ @stub_file.expects(:lstat).raises Errno::EACCES
@tidy.should_not be_tidy(@basepath)
end
it "should not be tidied if it is a directory and rmdirs is set to false" do
stat = mock 'stat', :ftype => "directory"
- File.expects(:lstat).with(@basepath).returns stat
+ @stub_file.expects(:lstat).returns stat
@tidy.should_not be_tidy(@basepath)
end
diff --git a/spec/unit/type/user_spec.rb b/spec/unit/type/user_spec.rb
index dd3dca6d9..2877d25c5 100755
--- a/spec/unit/type/user_spec.rb
+++ b/spec/unit/type/user_spec.rb
@@ -339,6 +339,15 @@ describe Puppet::Type.type(:user) do
end
end
+ describe "when managing comment on Ruby 1.9", :if => String.respond_to?(:encode) do
+ it "should force value encoding to ASCII-8BIT" do
+ value = 'abcd'.encode(Encoding::UTF_8)
+ comment = described_class.new(:name => 'foo', :comment => value)
+ comment[:comment].should == 'abcd'
+ comment[:comment].encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+
describe "when manages_solaris_rbac is enabled" do
it "should support a :role value for ensure" do
expect { described_class.new(:name => 'foo', :ensure => :role) }.to_not raise_error
diff --git a/spec/unit/type_spec.rb b/spec/unit/type_spec.rb
index b160c743f..ca29d680e 100755
--- a/spec/unit/type_spec.rb
+++ b/spec/unit/type_spec.rb
@@ -1,9 +1,10 @@
#! /usr/bin/env ruby
require 'spec_helper'
-
+require 'puppet_spec/compiler'
describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
include PuppetSpec::Files
+ include PuppetSpec::Compiler
it "should be Comparable" do
a = Puppet::Type.type(:notify).new(:name => "a")
@@ -63,6 +64,28 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
end
end
+ it "can retrieve all set parameters" do
+ resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present, :tag => 'foo')
+ params = resource.parameters_with_value
+ [:name, :provider, :ensure, :fstype, :pass, :dump, :target, :loglevel, :tag].each do |name|
+ params.should be_include(resource.parameter(name))
+ end
+ end
+
+ it "can not return any `nil` values when retrieving all set parameters" do
+ resource = Puppet::Type.type(:mount).new(:name => "foo", :fstype => "bar", :pass => 1, :ensure => :present, :tag => 'foo')
+ params = resource.parameters_with_value
+ params.should_not be_include(nil)
+ end
+
+ it "can return an iterator for all set parameters" do
+ resource = Puppet::Type.type(:notify).new(:name=>'foo',:message=>'bar',:tag=>'baz',:require=> "File['foo']")
+ params = [:name, :message, :withpath, :loglevel, :tag, :require]
+ resource.eachparameter { |param|
+ params.should be_include(param.to_s.to_sym)
+ }
+ end
+
it "should have a method for setting default values for resources" do
Puppet::Type.type(:mount).new(:name => "foo").must respond_to(:set_default)
end
@@ -109,6 +132,36 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
Puppet::Type.type(:mount).new(:name => "foo").version.should == 0
end
+ it "reports the correct path even after path is used during setup of the type" do
+ Puppet::Type.newtype(:testing) do
+ newparam(:name) do
+ isnamevar
+ validate do |value|
+ path # forces the computation of the path
+ end
+ end
+ end
+
+ ral = compile_to_ral(<<-MANIFEST)
+ class something {
+ testing { something: }
+ }
+ include something
+ MANIFEST
+
+ ral.resource("Testing[something]").path.should == "/Stage[main]/Something/Testing[something]"
+ end
+
+ context "alias metaparam" do
+ it "creates a new name that can be used for resource references" do
+ ral = compile_to_ral(<<-MANIFEST)
+ notify { a: alias => c }
+ MANIFEST
+
+ expect(ral.resource("Notify[a]")).to eq(ral.resource("Notify[c]"))
+ end
+ end
+
context "resource attributes" do
let(:resource) {
resource = Puppet::Type.type(:mount).new(:name => "foo")
@@ -123,7 +176,8 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
end
it "should have tags" do
- resource.tags.should == ["mount", "foo"]
+ expect(resource).to be_tagged("mount")
+ expect(resource).to be_tagged("foo")
end
it "should have a path" do
@@ -165,13 +219,19 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
@resource.event.default_log_level.should == :warning
end
- {:file => "/my/file", :line => 50, :tags => %{foo bar}}.each do |attr, value|
+ {:file => "/my/file", :line => 50}.each do |attr, value|
it "should set the #{attr}" do
@resource.stubs(attr).returns value
@resource.event.send(attr).should == value
end
end
+ it "should set the tags" do
+ @resource.tag("abc", "def")
+ @resource.event.should be_tagged("abc")
+ @resource.event.should be_tagged("def")
+ end
+
it "should allow specification of event attributes" do
@resource.event(:status => "noop").status.should == "noop"
end
@@ -470,6 +530,28 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
end
end
+ describe "when #finish is called on a type" do
+ let(:post_hook_type) do
+ Puppet::Type.newtype(:finish_test) do
+ newparam(:name) { isnamevar }
+
+ newparam(:post) do
+ def post_compile
+ raise "post_compile hook ran"
+ end
+ end
+ end
+ end
+
+ let(:post_hook_resource) do
+ post_hook_type.new(:name => 'foo',:post => 'fake_value')
+ end
+
+ it "should call #post_compile on parameters that implement it" do
+ expect { post_hook_resource.finish }.to raise_error(RuntimeError, "post_compile hook ran")
+ end
+ end
+
it "should have a class method for converting a hash into a Puppet::Resource instance" do
Puppet::Type.type(:mount).must respond_to(:hash2resource)
end
@@ -588,7 +670,7 @@ describe Puppet::Type, :unless => Puppet.features.microsoft_windows? do
resource.should be_a Puppet::Resource
resource[:fstype].should == 15
resource[:remounts].should == :true
- resource.tags.should =~ %w{foo bar baz mount}
+ resource.tags.should == Puppet::Util::TagSet.new(%w{foo bar baz mount})
end
end
diff --git a/spec/unit/util/adsi_spec.rb b/spec/unit/util/adsi_spec.rb
index 3b851f5f1..974aba79c 100755
--- a/spec/unit/util/adsi_spec.rb
+++ b/spec/unit/util/adsi_spec.rb
@@ -52,13 +52,48 @@ describe Puppet::Util::ADSI do
end
end
+ describe ".sid_uri", :if => Puppet.features.microsoft_windows? do
+ it "should raise an error when the input is not a SID object" do
+ [Object.new, {}, 1, :symbol, '', nil].each do |input|
+ expect {
+ Puppet::Util::ADSI.sid_uri(input)
+ }.to raise_error(Puppet::Error, /Must use a valid SID object/)
+ end
+ end
+
+ it "should return a SID uri for a well-known SID (SYSTEM)" do
+ sid = Win32::Security::SID.new('SYSTEM')
+ Puppet::Util::ADSI.sid_uri(sid).should == 'WinNT://S-1-5-18'
+ end
+ end
+
describe Puppet::Util::ADSI::User do
let(:username) { 'testuser' }
+ let(:domain) { 'DOMAIN' }
+ let(:domain_username) { "#{domain}\\#{username}"}
it "should generate the correct URI" do
Puppet::Util::ADSI::User.uri(username).should == "WinNT://./#{username},user"
end
+ it "should generate the correct URI for a user with a domain" do
+ Puppet::Util::ADSI::User.uri(username, domain).should == "WinNT://#{domain}/#{username},user"
+ end
+
+ it "should be able to parse a username without a domain" do
+ Puppet::Util::ADSI::User.parse_name(username).should == [username, '.']
+ end
+
+ it "should be able to parse a username with a domain" do
+ Puppet::Util::ADSI::User.parse_name(domain_username).should == [username, domain]
+ end
+
+ it "should raise an error with a username that contains a /" do
+ expect {
+ Puppet::Util::ADSI::User.parse_name("#{domain}/#{username}")
+ }.to raise_error(Puppet::Error, /Value must be in DOMAIN\\user style syntax/)
+ end
+
it "should be able to create a user" do
adsi_user = stub('adsi')
@@ -76,6 +111,11 @@ describe Puppet::Util::ADSI do
Puppet::Util::ADSI::User.exists?(username).should be_true
end
+ it "should be able to check the existence of a domain user" do
+ Puppet::Util::ADSI.expects(:connect).with("WinNT://#{domain}/#{username},user").returns connection
+ Puppet::Util::ADSI::User.exists?(domain_username).should be_true
+ end
+
it "should be able to delete a user" do
connection.expects(:Delete).with('user', username)
@@ -85,7 +125,7 @@ describe Puppet::Util::ADSI do
it "should return an enumeration of IADsUser wrapped objects" do
name = 'Administrator'
wmi_users = [stub('WMI', :name => name)]
- Puppet::Util::ADSI.expects(:execquery).with("select name from win32_useraccount").returns(wmi_users)
+ Puppet::Util::ADSI.expects(:execquery).with('select name from win32_useraccount where localaccount = "TRUE"').returns(wmi_users)
native_user = stub('IADsUser')
homedir = "C:\\Users\\#{name}"
@@ -99,7 +139,8 @@ describe Puppet::Util::ADSI do
end
describe "an instance" do
- let(:adsi_user) { stub 'user' }
+ let(:adsi_user) { stub('user', :objectSID => []) }
+ let(:sid) { stub(:account => username, :domain => 'testcomputername') }
let(:user) { Puppet::Util::ADSI::User.new(username, adsi_user) }
it "should provide its groups as a list of names" do
@@ -133,14 +174,16 @@ describe Puppet::Util::ADSI do
user.password = 'pwd'
end
- it "should generate the correct URI" do
- user.uri.should == "WinNT://./#{username},user"
+ it "should generate the correct URI",:if => Puppet.features.microsoft_windows? do
+ Puppet::Util::Windows::Security.stubs(:octet_string_to_sid_object).returns(sid)
+ user.uri.should == "WinNT://testcomputername/#{username},user"
end
- describe "when given a set of groups to which to add the user" do
+ describe "when given a set of groups to which to add the user", :if => Puppet.features.microsoft_windows? do
let(:groups_to_set) { 'group1,group2' }
before(:each) do
+ Puppet::Util::Windows::Security.stubs(:octet_string_to_sid_object).returns(sid)
user.expects(:groups).returns ['group2', 'group3']
end
@@ -152,6 +195,7 @@ describe Puppet::Util::ADSI do
group3 = stub 'group1'
group3.expects(:Remove).with("WinNT://testcomputername/#{username},user")
+ Puppet::Util::ADSI.expects(:sid_uri).with(sid).returns("WinNT://testcomputername/#{username},user").twice
Puppet::Util::ADSI.expects(:connect).with('WinNT://./group1,group').returns group1
Puppet::Util::ADSI.expects(:connect).with('WinNT://./group3,group').returns group3
@@ -164,6 +208,7 @@ describe Puppet::Util::ADSI do
group1 = stub 'group1'
group1.expects(:Add).with("WinNT://testcomputername/#{username},user")
+ Puppet::Util::ADSI.expects(:sid_uri).with(sid).returns("WinNT://testcomputername/#{username},user")
Puppet::Util::ADSI.expects(:connect).with('WinNT://./group1,group').returns group1
user.set_groups(groups_to_set, true)
@@ -179,19 +224,58 @@ describe Puppet::Util::ADSI do
describe "an instance" do
let(:adsi_group) { stub 'group' }
let(:group) { Puppet::Util::ADSI::Group.new(groupname, adsi_group) }
+ let(:someone_sid){ stub(:account => 'someone', :domain => 'testcomputername')}
+
+ it "should be able to add a member (deprecated)", :if => Puppet.features.microsoft_windows? do
+ Puppet.expects(:deprecation_warning).with('Puppet::Util::ADSI::Group#add_members is deprecated; please use Puppet::Util::ADSI::Group#add_member_sids')
+
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('someone').returns(someone_sid)
+ Puppet::Util::ADSI.expects(:sid_uri).with(someone_sid).returns("WinNT://testcomputername/someone,user")
- it "should be able to add a member" do
adsi_group.expects(:Add).with("WinNT://testcomputername/someone,user")
group.add_member('someone')
end
- it "should be able to remove a member" do
+ it "should raise when adding a member that can't resolve to a SID (deprecated)", :if => Puppet.features.microsoft_windows? do
+ expect {
+ group.add_member('foobar')
+ }.to raise_error(Puppet::Error, /Could not resolve username: foobar/)
+ end
+
+ it "should be able to remove a member (deprecated)", :if => Puppet.features.microsoft_windows? do
+ Puppet.expects(:deprecation_warning).with('Puppet::Util::ADSI::Group#remove_members is deprecated; please use Puppet::Util::ADSI::Group#remove_member_sids')
+
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('someone').returns(someone_sid)
+ Puppet::Util::ADSI.expects(:sid_uri).with(someone_sid).returns("WinNT://testcomputername/someone,user")
+
adsi_group.expects(:Remove).with("WinNT://testcomputername/someone,user")
group.remove_member('someone')
end
+ it "should raise when removing a member that can't resolve to a SID (deprecated)", :if => Puppet.features.microsoft_windows? do
+ expect {
+ group.remove_member('foobar')
+ }.to raise_error(Puppet::Error, /Could not resolve username: foobar/)
+ end
+
+ describe "should be able to use SID objects", :if => Puppet.features.microsoft_windows? do
+ let(:system) { Puppet::Util::Windows::Security.name_to_sid_object('SYSTEM') }
+
+ it "to add a member" do
+ adsi_group.expects(:Add).with("WinNT://S-1-5-18")
+
+ group.add_member_sids(system)
+ end
+
+ it "to remove a member" do
+ adsi_group.expects(:Remove).with("WinNT://S-1-5-18")
+
+ group.remove_member_sids(system)
+ end
+ end
+
it "should provide its groups as a list of names" do
names = ['user1', 'user2']
@@ -202,14 +286,38 @@ describe Puppet::Util::ADSI do
group.members.should =~ names
end
- it "should be able to add a list of users to a group" do
- names = ['user1', 'user2']
- adsi_group.expects(:Members).returns names.map{|n| stub(:Name => n)}
+ it "should be able to add a list of users to a group", :if => Puppet.features.microsoft_windows? do
+ names = ['DOMAIN\user1', 'user2']
+ sids = [
+ stub(:account => 'user1', :domain => 'DOMAIN'),
+ stub(:account => 'user2', :domain => 'testcomputername'),
+ stub(:account => 'user3', :domain => 'DOMAIN2'),
+ ]
+
+ # use stubbed objectSid on member to return stubbed SID
+ Puppet::Util::Windows::Security.expects(:octet_string_to_sid_object).with([0]).returns(sids[0])
+ Puppet::Util::Windows::Security.expects(:octet_string_to_sid_object).with([1]).returns(sids[1])
- adsi_group.expects(:Remove).with('WinNT://testcomputername/user1,user')
- adsi_group.expects(:Add).with('WinNT://testcomputername/user3,user')
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('user2').returns(sids[1])
+ Puppet::Util::Windows::Security.expects(:name_to_sid_object).with('DOMAIN2\user3').returns(sids[2])
+
+ Puppet::Util::ADSI.expects(:sid_uri).with(sids[0]).returns("WinNT://DOMAIN/user1,user")
+ Puppet::Util::ADSI.expects(:sid_uri).with(sids[2]).returns("WinNT://DOMAIN2/user3,user")
+
+ members = names.each_with_index.map{|n,i| stub(:Name => n, :objectSID => [i])}
+ adsi_group.expects(:Members).returns members
+
+ adsi_group.expects(:Remove).with('WinNT://DOMAIN/user1,user')
+ adsi_group.expects(:Add).with('WinNT://DOMAIN2/user3,user')
+
+ group.set_members(['user2', 'DOMAIN2\user3'])
+ end
- group.set_members(['user2', 'user3'])
+ it "should raise an error when a username does not resolve to a SID", :if => Puppet.features.microsoft_windows? do
+ expect {
+ adsi_group.expects(:Members).returns []
+ group.set_members(['foobar'])
+ }.to raise_error(Puppet::Error, /Could not resolve username: foobar/)
end
it "should generate the correct URI" do
@@ -248,7 +356,7 @@ describe Puppet::Util::ADSI do
it "should return an enumeration of IADsGroup wrapped objects" do
name = 'Administrators'
wmi_groups = [stub('WMI', :name => name)]
- Puppet::Util::ADSI.expects(:execquery).with("select name from win32_group").returns(wmi_groups)
+ Puppet::Util::ADSI.expects(:execquery).with('select name from win32_group where localaccount = "TRUE"').returns(wmi_groups)
native_group = stub('IADsGroup')
native_group.expects(:Members).returns([stub(:Name => 'Administrator')])
diff --git a/spec/unit/util/autoload_spec.rb b/spec/unit/util/autoload_spec.rb
index 933855914..4a0782ac7 100755
--- a/spec/unit/util/autoload_spec.rb
+++ b/spec/unit/util/autoload_spec.rb
@@ -71,7 +71,7 @@ describe Puppet::Util::Autoload do
[RuntimeError, LoadError, SyntaxError].each do |error|
it "should die with Puppet::Error if a #{error.to_s} exception is thrown" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.expects(:load).raises error
@@ -84,7 +84,7 @@ describe Puppet::Util::Autoload do
end
it "should register loaded files with the autoloader" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.stubs(:load)
@autoload.load("myfile")
@@ -94,7 +94,7 @@ describe Puppet::Util::Autoload do
end
it "should be seen by loaded? on the instance using the short name" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.stubs(:load)
@autoload.load("myfile")
@@ -104,7 +104,7 @@ describe Puppet::Util::Autoload do
end
it "should register loaded files with the main loaded file list so they are not reloaded by ruby" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.stubs(:load)
@autoload.load("myfile")
@@ -117,7 +117,7 @@ describe Puppet::Util::Autoload do
it "should load the first file in the searchpath" do
@autoload.stubs(:search_directories).returns [make_absolute("/a"), make_absolute("/b")]
FileTest.stubs(:directory?).returns true
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.expects(:load).with(make_absolute("/a/tmp/myfile.rb"), optionally(anything))
@autoload.load("myfile")
@@ -126,7 +126,7 @@ describe Puppet::Util::Autoload do
end
it "should treat equivalent paths to a loaded file as loaded" do
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.stubs(:load)
@autoload.load("myfile")
@@ -144,7 +144,7 @@ describe Puppet::Util::Autoload do
@autoload.class.stubs(:search_directories).returns [make_absolute("/a")]
FileTest.stubs(:directory?).returns true
Dir.stubs(:glob).returns [make_absolute("/a/foo/file.rb")]
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
@time_a = Time.utc(2010, 'jan', 1, 6, 30)
File.stubs(:mtime).returns @time_a
@@ -185,7 +185,7 @@ describe Puppet::Util::Autoload do
it "changes should be seen by changed? on the instance using the short name" do
File.stubs(:mtime).returns(@first_time)
- File.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
Kernel.stubs(:load)
@autoload.load("myfile")
@autoload.loaded?("myfile").should be
@@ -206,14 +206,14 @@ describe Puppet::Util::Autoload do
it "should reload if mtime changes" do
File.stubs(:mtime).with(@file_a).returns(@first_time + 60)
- File.stubs(:exist?).with(@file_a).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_a).returns true
Kernel.expects(:load).with(@file_a, optionally(anything))
@autoload.class.reload_changed
end
it "should do nothing if the file is deleted" do
File.stubs(:mtime).with(@file_a).raises(Errno::ENOENT)
- File.stubs(:exist?).with(@file_a).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_a).returns false
Kernel.expects(:load).never
@autoload.class.reload_changed
end
@@ -228,8 +228,8 @@ describe Puppet::Util::Autoload do
File.expects(:mtime).with(@file_a).returns(@first_time)
@autoload.class.mark_loaded("file", @file_a)
File.stubs(:mtime).with(@file_a).raises(Errno::ENOENT)
- File.stubs(:exist?).with(@file_a).returns false
- File.stubs(:exist?).with(@file_b).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_a).returns false
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_b).returns true
File.stubs(:mtime).with(@file_b).returns @first_time
Kernel.expects(:load).with(@file_b, optionally(anything))
@autoload.class.reload_changed
@@ -238,11 +238,11 @@ describe Puppet::Util::Autoload do
it "should load a/file when b/file is loaded and a/file is created" do
File.stubs(:mtime).with(@file_b).returns @first_time
- File.stubs(:exist?).with(@file_b).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_b).returns true
@autoload.class.mark_loaded("file", @file_b)
File.stubs(:mtime).with(@file_a).returns @first_time
- File.stubs(:exist?).with(@file_a).returns true
+ Puppet::FileSystem::File.stubs(:exist?).with(@file_a).returns true
Kernel.expects(:load).with(@file_a, optionally(anything))
@autoload.class.reload_changed
@autoload.class.send(:loaded)["file"].should == [@file_a, @first_time]
diff --git a/spec/unit/util/backups_spec.rb b/spec/unit/util/backups_spec.rb
index 8d3ea1956..654ddb788 100755
--- a/spec/unit/util/backups_spec.rb
+++ b/spec/unit/util/backups_spec.rb
@@ -20,7 +20,7 @@ describe Puppet::Util::Backups do
file = Puppet::Type.type(:file).new(:name => path)
file.expects(:bucket).never
- FileTest.expects(:exists?).with(path).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns false
file.perform_backup
end
@@ -29,23 +29,25 @@ describe Puppet::Util::Backups do
file = Puppet::Type.type(:file).new(:name => path, :backup => false)
file.expects(:bucket).never
- FileTest.expects(:exists?).never
+ Puppet::FileSystem::File.expects(:exist?).never
file.perform_backup
end
it "a bucket should be used when provided" do
- File.stubs(:lstat).with(path).returns(mock('lstat', :ftype => 'file'))
+ stub_file = stub(path, :lstat => mock('lstat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
bucket.expects(:backup).with(path).returns("mysum")
- FileTest.expects(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns(true)
file.perform_backup
end
it "should propagate any exceptions encountered when backing up to a filebucket" do
- File.stubs(:lstat).with(path).returns(mock('lstat', :ftype => 'file'))
+ stub_file = stub(path, :lstat => mock('lstat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
bucket.expects(:backup).raises ArgumentError
- FileTest.expects(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns(true)
lambda { file.perform_backup }.should raise_error(ArgumentError)
end
@@ -56,35 +58,39 @@ describe Puppet::Util::Backups do
let(:file) { Puppet::Type.type(:file).new(:name => path, :backup => '.'+ext) }
it "should remove any local backup if one exists" do
- File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file")
- File.expects(:unlink).with(backup)
+ stub_file = stub(backup, :lstat => stub('stat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(backup).returns stub_file
+ Puppet::FileSystem::File.expects(:unlink).with(backup)
FileUtils.stubs(:cp_r)
- FileTest.expects(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns(true)
file.perform_backup
end
it "should fail when the old backup can't be removed" do
- File.expects(:lstat).with(backup).returns stub("stat", :ftype => "file")
- File.expects(:unlink).with(backup).raises ArgumentError
+ stub_file = stub(backup, :lstat => stub('stat', :ftype => 'file'))
+ Puppet::FileSystem::File.expects(:new).with(backup).returns stub_file
+ Puppet::FileSystem::File.expects(:unlink).with(backup).raises ArgumentError
FileUtils.expects(:cp_r).never
- FileTest.expects(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns(true)
lambda { file.perform_backup }.should raise_error(Puppet::Error)
end
it "should not try to remove backups that don't exist" do
- File.expects(:lstat).with(backup).raises(Errno::ENOENT)
- File.expects(:unlink).with(backup).never
+ stub_file = stub(backup)
+ Puppet::FileSystem::File.expects(:new).with(backup).returns stub_file
+ stub_file.expects(:lstat).raises(Errno::ENOENT)
+ Puppet::FileSystem::File.expects(:unlink).with(backup).never
FileUtils.stubs(:cp_r)
- FileTest.expects(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns(true)
file.perform_backup
end
it "a copy should be created in the local directory" do
FileUtils.expects(:cp_r).with(path, backup, :preserve => true)
- FileTest.stubs(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(path).returns(true)
file.perform_backup.should be_true
end
@@ -92,7 +98,7 @@ describe Puppet::Util::Backups do
it "should propagate exceptions if no backup can be created" do
FileUtils.expects(:cp_r).raises ArgumentError
- FileTest.stubs(:exists?).with(path).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(path).returns(true)
lambda { file.perform_backup }.should raise_error(Puppet::Error)
end
end
@@ -108,10 +114,11 @@ describe Puppet::Util::Backups do
bucket.expects(:backup).with(filename).returns true
- File.stubs(:lstat).with(path).returns(stub('lstat', :ftype => 'directory'))
+ stub_file = stub(path, :lstat => stub('stat', :ftype => 'directory'))
+ Puppet::FileSystem::File.expects(:new).with(path).returns stub_file
- FileTest.stubs(:exists?).with(path).returns(true)
- FileTest.stubs(:exists?).with(filename).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(path).returns(true)
+ Puppet::FileSystem::File.stubs(:exist?).with(filename).returns(true)
file.perform_backup
end
@@ -120,7 +127,8 @@ describe Puppet::Util::Backups do
file = Puppet::Type.type(:file).new(:name => path, :backup => 'foo', :recurse => true)
bucket.expects(:backup).never
- File.stubs(:stat).with(path).returns(stub('stat', :ftype => 'directory'))
+ stub_file = stub('file', :stat => stub('stat', :ftype => 'directory'))
+ Puppet::FileSystem::File.stubs(:new).with(path).returns stub_file
Find.expects(:find).never
file.perform_backup
diff --git a/spec/unit/util/checksums_spec.rb b/spec/unit/util/checksums_spec.rb
index e928ca8ae..0adff7a9a 100755
--- a/spec/unit/util/checksums_spec.rb
+++ b/spec/unit/util/checksums_spec.rb
@@ -132,7 +132,8 @@ describe Puppet::Util::Checksums do
file = "/my/file"
stat = mock 'stat', sum => "mysum"
- File.expects(:stat).with(file).returns(stat)
+ stub_file = stub(file, :stat => stat)
+ Puppet::FileSystem::File.expects(:new).with(file).returns stub_file
@summer.send(sum.to_s + "_file", file).should == "mysum"
end
diff --git a/spec/unit/util/command_line_spec.rb b/spec/unit/util/command_line_spec.rb
index 3d8f896d1..6ba8077c2 100755
--- a/spec/unit/util/command_line_spec.rb
+++ b/spec/unit/util/command_line_spec.rb
@@ -143,5 +143,46 @@ describe Puppet::Util::CommandLine do
Puppet::Util::CommandLine.available_subcommands
end
end
+
+ describe 'when setting process priority' do
+ let(:command_line) do
+ Puppet::Util::CommandLine.new("puppet", %w{ agent })
+ end
+
+ before :each do
+ Puppet::Util::CommandLine::ApplicationSubcommand.any_instance.stubs(:run)
+ end
+
+ it 'should never set priority by default' do
+ Process.expects(:setpriority).never
+
+ command_line.execute
+ end
+
+ it 'should lower the process priority if one has been specified' do
+ Puppet[:priority] = 10
+
+ Process.expects(:setpriority).with(0, Process.pid, 10)
+ command_line.execute
+ end
+
+ it 'should warn if trying to raise priority, but not privileged user' do
+ Puppet[:priority] = -10
+
+ Process.expects(:setpriority).raises(Errno::EACCES, 'Permission denied')
+ Puppet.expects(:warning).with("Failed to set process priority to '-10'")
+
+ command_line.execute
+ end
+
+ it "should warn if the platform doesn't support `Process.setpriority`" do
+ Puppet[:priority] = 15
+
+ Process.expects(:setpriority).raises(NotImplementedError, 'NotImplementedError: setpriority() function is unimplemented on this machine')
+ Puppet.expects(:warning).with("Failed to set process priority to '15'")
+
+ command_line.execute
+ end
+ end
end
end
diff --git a/spec/unit/util/docs_spec.rb b/spec/unit/util/docs_spec.rb
new file mode 100644
index 000000000..eb736ff72
--- /dev/null
+++ b/spec/unit/util/docs_spec.rb
@@ -0,0 +1,91 @@
+require 'spec_helper'
+
+describe Puppet::Util::Docs do
+
+ describe '.scrub' do
+ let(:my_cleaned_output) do
+ %q{This resource type uses the prescribed native tools for creating
+groups and generally uses POSIX APIs for retrieving information
+about them. It does not directly modify `/etc/passwd` or anything.
+
+* Just for fun, we'll add a list.
+* list item two,
+ which has some add'l lines included in it.
+
+And here's a code block:
+
+ this is the piece of code
+ it does something cool
+
+**Autorequires:** I would be listing autorequired resources here.}
+ end
+
+ it "strips the least common indent from multi-line strings, without mangling indentation beyond the least common indent" do
+ input = <<EOT
+ This resource type uses the prescribed native tools for creating
+ groups and generally uses POSIX APIs for retrieving information
+ about them. It does not directly modify `/etc/passwd` or anything.
+
+ * Just for fun, we'll add a list.
+ * list item two,
+ which has some add'l lines included in it.
+
+ And here's a code block:
+
+ this is the piece of code
+ it does something cool
+
+ **Autorequires:** I would be listing autorequired resources here.
+EOT
+ output = Puppet::Util::Docs.scrub(input)
+ expect(output).to eq my_cleaned_output
+ end
+
+ it "ignores the first line when calculating least common indent" do
+ input = "This resource type uses the prescribed native tools for creating
+ groups and generally uses POSIX APIs for retrieving information
+ about them. It does not directly modify `/etc/passwd` or anything.
+
+ * Just for fun, we'll add a list.
+ * list item two,
+ which has some add'l lines included in it.
+
+ And here's a code block:
+
+ this is the piece of code
+ it does something cool
+
+ **Autorequires:** I would be listing autorequired resources here."
+ output = Puppet::Util::Docs.scrub(input)
+ expect(output).to eq my_cleaned_output
+ end
+
+ it "strips trailing whitespace from each line, and strips trailing newlines at end" do
+ input = "This resource type uses the prescribed native tools for creating \n groups and generally uses POSIX APIs for retrieving information \n about them. It does not directly modify `/etc/passwd` or anything. \n\n * Just for fun, we'll add a list. \n * list item two,\n which has some add'l lines included in it. \n\n And here's a code block:\n\n this is the piece of code \n it does something cool \n\n **Autorequires:** I would be listing autorequired resources here. \n\n"
+ output = Puppet::Util::Docs.scrub(input)
+ expect(output).to eq my_cleaned_output
+ end
+
+ it "has no side effects on original input string" do
+ input = "First line \n second line \n \n indented line \n \n last line\n\n"
+ clean_input = "First line \n second line \n \n indented line \n \n last line\n\n"
+ not_used = Puppet::Util::Docs.scrub(input)
+ expect(input).to eq clean_input
+ end
+
+ it "does not include whitespace-only lines when calculating least common indent" do
+ input = "First line\n second line\n \n indented line\n\n last line"
+ expected_output = "First line\nsecond line\n\n indented line\n\nlast line"
+ #bogus_output = "First line\nsecond line\n\n indented line\n\nlast line"
+ output = Puppet::Util::Docs.scrub(input)
+ expect(output).to eq expected_output
+ end
+
+ it "accepts a least common indent of zero, thus not adding errors when input string is already scrubbed" do
+ expect(Puppet::Util::Docs.scrub(my_cleaned_output)).to eq my_cleaned_output
+ end
+
+
+ end
+end
+
diff --git a/spec/unit/util/execution_spec.rb b/spec/unit/util/execution_spec.rb
index 71af8f01f..7bb15cd75 100755
--- a/spec/unit/util/execution_spec.rb
+++ b/spec/unit/util/execution_spec.rb
@@ -306,11 +306,21 @@ describe Puppet::Util::Execution do
Puppet::Util::Execution.stubs(:execute_windows).returns(proc_info_stub)
Puppet::Util::Windows::Process.expects(:wait_process).with(process_handle).raises('whatever')
- Process.expects(:CloseHandle).with(thread_handle)
- Process.expects(:CloseHandle).with(process_handle)
+ Puppet::Util::Windows::Process.expects(:CloseHandle).with(thread_handle)
+ Puppet::Util::Windows::Process.expects(:CloseHandle).with(process_handle)
expect { Puppet::Util::Execution.execute('test command') }.to raise_error(RuntimeError)
end
+
+ it "should return the correct exit status even when exit status is greater than 256" do
+ real_exit_status = 3010
+
+ Puppet::Util::Execution.stubs(:execute_windows).returns(proc_info_stub)
+ stub_process_wait(real_exit_status)
+ $CHILD_STATUS.stubs(:exitstatus).returns(real_exit_status % 256) # The exitstatus is changed to be mod 256 so that ruby can fit it into 8 bits.
+
+ Puppet::Util::Execution.execute('test command', :failonfail => false).exitstatus.should == real_exit_status
+ end
end
end
@@ -509,7 +519,7 @@ describe Puppet::Util::Execution do
Tempfile.stubs(:new).returns(stdout)
stdout.write("My expected command output")
- Puppet::Util::Execution.execute('test command', :squelch => true).should == nil
+ Puppet::Util::Execution.execute('test command', :squelch => true).should == ''
end
it "should delete the file used for output if squelch is false" do
@@ -519,7 +529,7 @@ describe Puppet::Util::Execution do
Puppet::Util::Execution.execute('test command')
- File.should_not be_exist(path)
+ Puppet::FileSystem::File.exist?(path).should be_false
end
it "should not raise an error if the file is open" do
@@ -591,6 +601,20 @@ describe Puppet::Util::Execution do
Puppet::Util::Execution.execpipe('echo hello').should == 'hello'
end
+ it "should print meaningful debug message for string argument" do
+ Puppet::Util::Execution.expects(:debug).with("Executing 'echo hello'")
+ Puppet::Util::Execution.expects(:open).with('| echo hello 2>&1').returns('hello')
+ $CHILD_STATUS.expects(:==).with(0).returns(true)
+ Puppet::Util::Execution.execpipe('echo hello')
+ end
+
+ it "should print meaningful debug message for array argument" do
+ Puppet::Util::Execution.expects(:debug).with("Executing 'echo hello'")
+ Puppet::Util::Execution.expects(:open).with('| echo hello 2>&1').returns('hello')
+ $CHILD_STATUS.expects(:==).with(0).returns(true)
+ Puppet::Util::Execution.execpipe(['echo','hello'])
+ end
+
it "should execute an array by pasting together with spaces" do
Puppet::Util::Execution.expects(:open).with('| echo hello 2>&1').returns('hello')
$CHILD_STATUS.expects(:==).with(0).returns(true)
diff --git a/spec/unit/util/filetype_spec.rb b/spec/unit/util/filetype_spec.rb
index ecf7c3690..5d8f0b36d 100755
--- a/spec/unit/util/filetype_spec.rb
+++ b/spec/unit/util/filetype_spec.rb
@@ -16,15 +16,15 @@ describe Puppet::Util::FileType do
describe "when the file already exists" do
it "should return the file's contents when asked to read it" do
- File.expects(:exist?).with(path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns true
File.expects(:read).with(path).returns "my text"
file.read.should == "my text"
end
it "should unlink the file when asked to remove it" do
- File.expects(:exist?).with(path).returns true
- File.expects(:unlink).with(path)
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns true
+ Puppet::FileSystem::File.expects(:unlink).with(path)
file.remove
end
@@ -32,7 +32,7 @@ describe Puppet::Util::FileType do
describe "when the file does not exist" do
it "should return an empty string when asked to read the file" do
- File.expects(:exist?).with(path).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns false
file.read.should == ""
end
@@ -63,13 +63,13 @@ describe Puppet::Util::FileType do
describe "when backing up a file" do
it "should do nothing if the file does not exist" do
- File.expects(:exists?).with(path).returns false
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns false
file.expects(:bucket).never
file.backup
end
it "should use its filebucket to backup the file if it exists" do
- File.expects(:exists?).with(path).returns true
+ Puppet::FileSystem::File.expects(:exist?).with(path).returns true
bucket = mock 'bucket'
bucket.expects(:backup).with(path)
@@ -155,7 +155,7 @@ describe Puppet::Util::FileType do
end
after :each do
- File.should_not be_exist @tmp_cron_path
+ Puppet::FileSystem::File.exist?(@tmp_cron_path).should be_false
end
it "should run crontab as the target user on a temporary file" do
diff --git a/spec/unit/util/lockfile_spec.rb b/spec/unit/util/lockfile_spec.rb
index 4f3463429..8d10d5106 100644
--- a/spec/unit/util/lockfile_spec.rb
+++ b/spec/unit/util/lockfile_spec.rb
@@ -25,7 +25,7 @@ describe Puppet::Util::Lockfile do
it "should create a lock file" do
@lock.lock
- File.should be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_true
end
it "should create a lock file containing a string" do
@@ -49,7 +49,7 @@ describe Puppet::Util::Lockfile do
it "should clear the lock file" do
File.open(@lockfile, 'w') { |fd| fd.print("locked") }
@lock.unlock
- File.should_not be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_false
end
end
diff --git a/spec/unit/util/log/destinations_spec.rb b/spec/unit/util/log/destinations_spec.rb
index 332e8ad7c..b34b973cf 100755
--- a/spec/unit/util/log/destinations_spec.rb
+++ b/spec/unit/util/log/destinations_spec.rb
@@ -108,6 +108,38 @@ describe Puppet::Util::Log.desttypes[:syslog] do
end
end
+describe Puppet::Util::Log.desttypes[:logstash_event] do
+
+ describe "when using structured log format with logstash_event schema" do
+ before :each do
+ @msg = Puppet::Util::Log.new(:level => :info, :message => "So long, and thanks for all the fish.", :source => "a dolphin")
+ end
+
+ it "format should fix the hash to have the correct structure" do
+ dest = described_class.new
+ result = dest.format(@msg)
+ result["version"].should == 1
+ result["level"].should == :info
+ result["message"].should == "So long, and thanks for all the fish."
+ result["source"].should == "a dolphin"
+ # timestamp should be within 10 seconds
+ Time.parse(result["@timestamp"]).should >= ( Time.now - 10 )
+ end
+
+ it "format returns a structure that can be converted to json" do
+ dest = described_class.new
+ hash = dest.format(@msg)
+ JSON.parse(hash.to_json)
+ end
+
+ it "handle should send the output to stdout" do
+ $stdout.expects(:puts).once
+ dest = described_class.new
+ dest.handle(@msg)
+ end
+ end
+end
+
describe Puppet::Util::Log.desttypes[:console] do
let (:klass) { Puppet::Util::Log.desttypes[:console] }
diff --git a/spec/unit/util/monkey_patches_spec.rb b/spec/unit/util/monkey_patches_spec.rb
index cc487020c..13e10454c 100755
--- a/spec/unit/util/monkey_patches_spec.rb
+++ b/spec/unit/util/monkey_patches_spec.rb
@@ -280,6 +280,47 @@ describe OpenSSL::SSL::SSLContext do
end
end
+
+describe OpenSSL::X509::Store, :if => Puppet::Util::Platform.windows? do
+ let(:store) { described_class.new }
+ let(:cert) { OpenSSL::X509::Certificate.new(File.read(my_fixture('x509.pem'))) }
+
+ def with_root_certs(certs)
+ Puppet::Util::Windows::RootCerts.expects(:instance).returns(certs)
+ end
+
+ it "adds a root cert to the store" do
+ with_root_certs([cert])
+
+ store.set_default_paths
+ end
+
+ it "ignores duplicate root certs" do
+ with_root_certs([cert, cert])
+
+ store.expects(:add_cert).with(cert).once
+
+ store.set_default_paths
+ end
+
+ it "warns when adding a certificate that already exists" do
+ with_root_certs([cert])
+ store.add_cert(cert)
+
+ store.expects(:warn).with('Failed to add /DC=com/DC=microsoft/CN=Microsoft Root Certificate Authority')
+
+ store.set_default_paths
+ end
+
+ it "raises when adding an invalid certificate" do
+ with_root_certs(['notacert'])
+
+ expect {
+ store.set_default_paths
+ }.to raise_error(TypeError)
+ end
+end
+
describe SecureRandom do
it 'generates a properly formatted uuid' do
SecureRandom.uuid.should =~ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i
diff --git a/spec/unit/util/pidlock_spec.rb b/spec/unit/util/pidlock_spec.rb
index 3e70ce008..e9c28f2b0 100644
--- a/spec/unit/util/pidlock_spec.rb
+++ b/spec/unit/util/pidlock_spec.rb
@@ -47,7 +47,7 @@ describe Puppet::Util::Pidlock do
it "should create a lock file" do
@lock.lock
- File.should be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_true
end
it "should expose the lock file_path" do
@@ -74,7 +74,7 @@ describe Puppet::Util::Pidlock do
it "should get rid of the lock file" do
@lock.lock
@lock.unlock
- File.should_not be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_false
end
end
@@ -106,12 +106,12 @@ describe Puppet::Util::Pidlock do
describe "#lock" do
it "should clear stale locks" do
@lock.locked?
- File.should_not be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_false
end
it "should replace with new locks" do
@lock.lock
- File.should be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_true
@lock.lock_pid.should == 6789
@lock.should be_mine
@lock.should be_locked
@@ -125,7 +125,7 @@ describe Puppet::Util::Pidlock do
it "should not remove the lock file" do
@lock.unlock
- File.should be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_true
end
end
end
@@ -170,7 +170,7 @@ describe Puppet::Util::Pidlock do
it "should not remove the lock file" do
@lock.unlock
- File.should be_exists(@lockfile)
+ Puppet::FileSystem::File.exist?(@lockfile).should be_true
end
it "should still not be our lock" do
diff --git a/spec/unit/util/rdoc/parser_spec.rb b/spec/unit/util/rdoc/parser_spec.rb
index 476d15214..1699020a7 100755
--- a/spec/unit/util/rdoc/parser_spec.rb
+++ b/spec/unit/util/rdoc/parser_spec.rb
@@ -13,7 +13,9 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
include PuppetSpec::Files
before :each do
- File.stubs(:stat).with("init.pp")
+ stub_file = stub('init.pp', :stat => stub())
+ # Ruby 1.8.7 needs the following call to be stubs and not expects
+ Puppet::FileSystem::File.stubs(:new).with('init.pp').returns stub_file
@top_level = stub_everything 'toplevel', :file_relative_name => "init.pp"
@parser = RDoc::Parser.new(@top_level, "module/manifests/init.pp", nil, Options.instance, RDoc::Stats.new)
end
@@ -82,7 +84,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
File.stubs(:open).returns("readme")
@parser.stubs(:parse_elements)
- @module.expects(:comment=).with("readme")
+ @module.expects(:add_comment).with("readme", "module/manifests/init.pp")
@parser.scan_top_level(@topcontainer)
end
@@ -93,7 +95,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
File.stubs(:open).returns("readme")
@parser.stubs(:parse_elements)
- @module.expects(:comment=).with("readme")
+ @module.expects(:add_comment).with("readme", "module/manifests/init.pp")
@parser.scan_top_level(@topcontainer)
end
@@ -105,7 +107,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
File.stubs(:open).with("module/README.rdoc", "r").returns("readme.rdoc")
@parser.stubs(:parse_elements)
- @module.expects(:comment=).with("readme.rdoc")
+ @module.expects(:add_comment).with("readme.rdoc", "module/manifests/init.pp")
@parser.scan_top_level(@topcontainer)
end
@@ -311,7 +313,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
end
it "should associate the node documentation to the rdoc node" do
- @rdoc_node.expects(:comment=).with("mydoc")
+ @rdoc_node.expects(:add_comment).with("mydoc", "file")
@parser.document_node("mynode", @node, @class)
end
@@ -360,7 +362,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
end
it "should associate the node documentation to the rdoc class" do
- @rdoc_class.expects(:comment=).with("mydoc")
+ @rdoc_class.expects(:add_comment).with("mydoc", "file")
@parser.document_class("mynode", @class, @module)
end
@@ -397,7 +399,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
before(:each) do
@class = stub_everything 'class'
@code = stub_everything 'code'
- @code.stubs(:is_a?).with(Puppet::Parser::AST::ASTArray).returns(true)
+ @code.stubs(:is_a?).with(Puppet::Parser::AST::BlockExpression).returns(true)
end
it "should also scan mono-instruction code" do
@@ -435,7 +437,7 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
before(:each) do
@class = stub_everything 'class'
@code = stub_everything 'code'
- @code.stubs(:is_a?).with(Puppet::Parser::AST::ASTArray).returns(true)
+ @code.stubs(:is_a?).with(Puppet::Parser::AST::BlockExpression).returns(true)
end
it "should also scan mono-instruction code" do
@@ -457,11 +459,11 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
@class = stub_everything 'class'
@stmt = stub_everything 'stmt', :name => "myvar", :value => "myvalue", :doc => "mydoc"
- @stmt.stubs(:is_a?).with(Puppet::Parser::AST::ASTArray).returns(false)
+ @stmt.stubs(:is_a?).with(Puppet::Parser::AST::BlockExpression).returns(false)
@stmt.stubs(:is_a?).with(Puppet::Parser::AST::VarDef).returns(true)
@code = stub_everything 'code'
- @code.stubs(:is_a?).with(Puppet::Parser::AST::ASTArray).returns(true)
+ @code.stubs(:is_a?).with(Puppet::Parser::AST::BlockExpression).returns(true)
end
it "should recursively register variables to the current container" do
@@ -483,17 +485,17 @@ describe "RDoc::Parser", :if => Puppet.features.rdoc1? do
@class = stub_everything 'class'
@stmt = Puppet::Parser::AST::Resource.new(
:type => "File",
- :instances => Puppet::Parser::AST::ASTArray.new(:children => [
+ :instances => Puppet::Parser::AST::BlockExpression.new(:children => [
Puppet::Parser::AST::ResourceInstance.new(
:title => Puppet::Parser::AST::Name.new(:value => "myfile"),
- :parameters => Puppet::Parser::AST::ASTArray.new(:children => [])
+ :parameters => Puppet::Parser::AST::BlockExpression.new(:children => [])
)
]),
:doc => 'mydoc'
)
@code = stub_everything 'code'
- @code.stubs(:is_a?).with(Puppet::Parser::AST::ASTArray).returns(true)
+ @code.stubs(:is_a?).with(Puppet::Parser::AST::BlockExpression).returns(true)
end
it "should register a PuppetResource to the current container" do
diff --git a/spec/unit/util/rdoc_spec.rb b/spec/unit/util/rdoc_spec.rb
index b13591374..f71bf7939 100755
--- a/spec/unit/util/rdoc_spec.rb
+++ b/spec/unit/util/rdoc_spec.rb
@@ -5,15 +5,7 @@ require 'puppet/util/rdoc'
require 'rdoc/rdoc'
describe Puppet::Util::RDoc do
- it "should fail with a clear error without RDoc 1.*" do
- Puppet.features.stubs(:rdoc1?).returns(false)
-
- expect {
- Puppet::Util::RDoc.rdoc("output", [])
- }.to raise_error(/the version of RDoc .* is not supported/)
- end
-
- describe "when generating RDoc HTML documentation", :if => Puppet.features.rdoc1? do
+ describe "when generating RDoc HTML documentation" do
before :each do
@rdoc = stub_everything 'rdoc'
RDoc::RDoc.stubs(:new).returns(@rdoc)
@@ -24,12 +16,6 @@ describe Puppet::Util::RDoc do
Puppet::Util::RDoc.rdoc("output", [])
end
- it "should install the Puppet HTML Generator into RDoc generators" do
- Puppet::Util::RDoc.rdoc("output", [])
-
- RDoc::RDoc::GENERATORS["puppet"].file_name.should == "puppet/util/rdoc/generators/puppet_generator.rb"
- end
-
it "should tell RDoc to generate documentation using the Puppet generator" do
@rdoc.expects(:document).with { |args| args.include?("--fmt") and args.include?("puppet") }
@@ -48,18 +34,26 @@ describe Puppet::Util::RDoc do
Puppet::Util::RDoc.rdoc("output", [], "utf-8")
end
- it "should tell RDoc to force updates of indices when RDoc supports it" do
- Options::OptionList.stubs(:options).returns([["--force-update", "-U", 0 ]])
- @rdoc.expects(:document).with { |args| args.include?("--force-update") }
+ describe "with rdoc1", :if => Puppet.features.rdoc1? do
+ it "should install the Puppet HTML Generator into RDoc generators" do
+ Puppet::Util::RDoc.rdoc("output", [])
- Puppet::Util::RDoc.rdoc("output", [])
- end
+ RDoc::RDoc::GENERATORS["puppet"].file_name.should == "puppet/util/rdoc/generators/puppet_generator.rb"
+ end
- it "should not tell RDoc to force updates of indices when RDoc doesn't support it" do
- Options::OptionList.stubs(:options).returns([])
- @rdoc.expects(:document).never.with { |args| args.include?("--force-update") }
+ it "should tell RDoc to force updates of indices when RDoc supports it" do
+ ::Options::OptionList.stubs(:options).returns([["--force-update", "-U", 0 ]])
+ @rdoc.expects(:document).with { |args| args.include?("--force-update") }
- Puppet::Util::RDoc.rdoc("output", [])
+ Puppet::Util::RDoc.rdoc("output", [])
+ end
+
+ it "should not tell RDoc to force updates of indices when RDoc doesn't support it" do
+ ::Options::OptionList.stubs(:options).returns([])
+ @rdoc.expects(:document).never.with { |args| args.include?("--force-update") }
+
+ Puppet::Util::RDoc.rdoc("output", [])
+ end
end
it "should tell RDoc to use the given outputdir" do
diff --git a/spec/unit/util/resource_template_spec.rb b/spec/unit/util/resource_template_spec.rb
index ee4c1b866..0e6037119 100755
--- a/spec/unit/util/resource_template_spec.rb
+++ b/spec/unit/util/resource_template_spec.rb
@@ -6,20 +6,20 @@ require 'puppet/util/resource_template'
describe Puppet::Util::ResourceTemplate do
describe "when initializing" do
it "should fail if the template does not exist" do
- FileTest.expects(:exist?).with("/my/template").returns false
+ Puppet::FileSystem::File.expects(:exist?).with("/my/template").returns false
lambda { Puppet::Util::ResourceTemplate.new("/my/template", mock('resource')) }.should raise_error(ArgumentError)
end
it "should not create the ERB template" do
ERB.expects(:new).never
- FileTest.expects(:exist?).with("/my/template").returns true
+ Puppet::FileSystem::File.expects(:exist?).with("/my/template").returns true
Puppet::Util::ResourceTemplate.new("/my/template", mock('resource'))
end
end
describe "when evaluating" do
before do
- FileTest.stubs(:exist?).returns true
+ Puppet::FileSystem::File.stubs(:exist?).returns true
File.stubs(:read).returns "eh"
@template = stub 'template', :result => nil
diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb
index ac2bc2977..1357b981a 100755
--- a/spec/unit/util/selinux_spec.rb
+++ b/spec/unit/util/selinux_spec.rb
@@ -123,7 +123,8 @@ describe Puppet::Util::SELinux do
it "should return a context if a default context exists" do
self.expects(:selinux_support?).returns true
fstat = stub 'File::Stat', :mode => 0
- File.expects(:lstat).with("/foo").returns fstat
+ stub_file = stub('/foo', :lstat => fstat)
+ Puppet::FileSystem::File.expects(:new).with('/foo').returns stub_file
self.expects(:find_fs).with("/foo").returns "ext3"
Selinux.expects(:matchpathcon).with("/foo", 0).returns [0, "user_u:role_r:type_t:s0"]
get_selinux_default_context("/foo").should == "user_u:role_r:type_t:s0"
@@ -150,7 +151,8 @@ describe Puppet::Util::SELinux do
it "should return nil if matchpathcon returns failure" do
self.expects(:selinux_support?).returns true
fstat = stub 'File::Stat', :mode => 0
- File.expects(:lstat).with("/foo").returns fstat
+ stub_file = stub('/foo', :lstat => fstat)
+ Puppet::FileSystem::File.expects(:new).with('/foo').returns stub_file
self.expects(:find_fs).with("/foo").returns "ext3"
Selinux.expects(:matchpathcon).with("/foo", 0).returns -1
get_selinux_default_context("/foo").should be_nil
diff --git a/spec/unit/util/storage_spec.rb b/spec/unit/util/storage_spec.rb
index ba1675981..582bd2422 100755
--- a/spec/unit/util/storage_spec.rb
+++ b/spec/unit/util/storage_spec.rb
@@ -77,7 +77,7 @@ describe Puppet::Util::Storage do
end
it "should not fail to load" do
- FileTest.exists?(@path).should be_false
+ Puppet::FileSystem::File.exist?(@path).should be_false
Puppet[:statedir] = @path
Puppet::Util::Storage.load
Puppet[:statefile] = @path
@@ -85,7 +85,7 @@ describe Puppet::Util::Storage do
end
it "should not lose its internal state when load() is called" do
- FileTest.exists?(@path).should be_false
+ Puppet::FileSystem::File.exist?(@path).should be_false
Puppet::Util::Storage.cache(:yayness)
Puppet::Util::Storage.state.should == {:yayness=>{}}
@@ -176,12 +176,12 @@ describe Puppet::Util::Storage do
end
it "should create the state file if it does not exist" do
- FileTest.exists?(Puppet[:statefile]).should be_false
+ Puppet::FileSystem::File.exist?(Puppet[:statefile]).should be_false
Puppet::Util::Storage.cache(:yayness)
Puppet::Util::Storage.store
- FileTest.exists?(Puppet[:statefile]).should be_true
+ Puppet::FileSystem::File.exist?(Puppet[:statefile]).should be_true
end
it "should raise an exception if the state file is not a regular file" do
diff --git a/spec/unit/util/suidmanager_spec.rb b/spec/unit/util/suidmanager_spec.rb
index 5962e4362..f8ba883f5 100755
--- a/spec/unit/util/suidmanager_spec.rb
+++ b/spec/unit/util/suidmanager_spec.rb
@@ -231,6 +231,13 @@ describe Puppet::Util::SUIDManager do
output.first.should == 'output'
output.last.should be_a(Process::Status)
end
+
+ it "should log a deprecation notice" do
+ Puppet::Util::Execution.stubs(:execute).returns("success")
+ Puppet.expects(:deprecation_warning).with('Puppet::Util::SUIDManager.run_and_capture is deprecated; please use Puppet::Util::Execution.execute instead.')
+
+ output = Puppet::Util::SUIDManager.run_and_capture 'yay', user[:uid], user[:gid]
+ end
end
end
diff --git a/spec/unit/util/tag_set_spec.rb b/spec/unit/util/tag_set_spec.rb
new file mode 100644
index 000000000..c59674fcb
--- /dev/null
+++ b/spec/unit/util/tag_set_spec.rb
@@ -0,0 +1,46 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+
+require 'puppet/util/tag_set'
+
+RSpec::Matchers.define :be_one_of do |*expected|
+ match do |actual|
+ expected.include? actual
+ end
+
+ failure_message_for_should do |actual|
+ "expected #{actual.inspect} to be one of #{expected.map(&:inspect).join(' or ')}"
+ end
+end
+
+describe Puppet::Util::TagSet do
+ let(:set) { Puppet::Util::TagSet.new }
+
+ it 'serializes to yaml as an array' do
+ array = ['a', :b, 1, 5.4]
+ set.merge(array)
+
+ Set.new(YAML.load(set.to_yaml)).should == Set.new(array)
+ end
+
+ it 'deserializes from a yaml array' do
+ array = ['a', :b, 1, 5.4]
+
+ Puppet::Util::TagSet.from_yaml(array.to_yaml).should == Puppet::Util::TagSet.new(array)
+ end
+
+ it 'round trips through pson' do
+ array = ['a', 'b', 1, 5.4]
+ set.merge(array)
+
+ tes = Puppet::Util::TagSet.from_pson(PSON.parse(set.to_pson))
+ tes.should == set
+ end
+
+ it 'can join its elements with a string separator' do
+ array = ['a', 'b']
+ set.merge(array)
+
+ set.join(', ').should be_one_of('a, b', 'b, a')
+ end
+end
diff --git a/spec/unit/util/tagging_spec.rb b/spec/unit/util/tagging_spec.rb
index 67b766fe0..248e915e9 100755
--- a/spec/unit/util/tagging_spec.rb
+++ b/spec/unit/util/tagging_spec.rb
@@ -3,92 +3,129 @@ require 'spec_helper'
require 'puppet/util/tagging'
-describe Puppet::Util::Tagging, "when adding tags" do
- before do
- @tagger = Object.new
- @tagger.extend(Puppet::Util::Tagging)
- end
-
- it "should have a method for adding tags" do
- @tagger.should be_respond_to(:tag)
- end
-
- it "should have a method for returning all tags" do
- @tagger.should be_respond_to(:tags)
- end
+describe Puppet::Util::Tagging do
+ let(:tagger) { Object.new.extend(Puppet::Util::Tagging) }
it "should add tags to the returned tag list" do
- @tagger.tag("one")
- @tagger.tags.should be_include("one")
- end
-
- it "should not add duplicate tags to the returned tag list" do
- @tagger.tag("one")
- @tagger.tag("one")
- @tagger.tags.should == ["one"]
+ tagger.tag("one")
+ expect(tagger.tags).to include("one")
end
it "should return a duplicate of the tag list, rather than the original" do
- @tagger.tag("one")
- tags = @tagger.tags
+ tagger.tag("one")
+ tags = tagger.tags
tags << "two"
- @tagger.tags.should_not be_include("two")
+ expect(tagger.tags).to_not include("two")
end
it "should add all provided tags to the tag list" do
- @tagger.tag("one", "two")
- @tagger.tags.should be_include("one")
- @tagger.tags.should be_include("two")
+ tagger.tag("one", "two")
+ expect(tagger.tags).to include("one")
+ expect(tagger.tags).to include("two")
end
it "should fail on tags containing '*' characters" do
- expect { @tagger.tag("bad*tag") }.to raise_error(Puppet::ParseError)
+ expect { tagger.tag("bad*tag") }.to raise_error(Puppet::ParseError)
end
it "should fail on tags starting with '-' characters" do
- expect { @tagger.tag("-badtag") }.to raise_error(Puppet::ParseError)
+ expect { tagger.tag("-badtag") }.to raise_error(Puppet::ParseError)
end
it "should fail on tags containing ' ' characters" do
- expect { @tagger.tag("bad tag") }.to raise_error(Puppet::ParseError)
+ expect { tagger.tag("bad tag") }.to raise_error(Puppet::ParseError)
end
it "should allow alpha tags" do
- expect { @tagger.tag("good_tag") }.to_not raise_error
+ expect { tagger.tag("good_tag") }.not_to raise_error
end
it "should allow tags containing '.' characters" do
- expect { @tagger.tag("good.tag") }.to_not raise_error
+ expect { tagger.tag("good.tag") }.to_not raise_error(Puppet::ParseError)
end
it "should add qualified classes as tags" do
- @tagger.tag("one::two")
- @tagger.tags.should be_include("one::two")
+ tagger.tag("one::two")
+ expect(tagger.tags).to include("one::two")
end
it "should add each part of qualified classes as tags" do
- @tagger.tag("one::two::three")
- @tagger.tags.should be_include("one")
- @tagger.tags.should be_include("two")
- @tagger.tags.should be_include("three")
+ tagger.tag("one::two::three")
+ expect(tagger.tags).to include('one')
+ expect(tagger.tags).to include("two")
+ expect(tagger.tags).to include("three")
end
it "should indicate when the object is tagged with a provided tag" do
- @tagger.tag("one")
- @tagger.should be_tagged("one")
+ tagger.tag("one")
+ expect(tagger).to be_tagged("one")
end
it "should indicate when the object is not tagged with a provided tag" do
- @tagger.should_not be_tagged("one")
+ expect(tagger).to_not be_tagged("one")
end
it "should indicate when the object is tagged with any tag in an array" do
- @tagger.tag("one")
- @tagger.should be_tagged("one","two","three")
+ tagger.tag("one")
+ expect(tagger).to be_tagged("one","two","three")
end
it "should indicate when the object is not tagged with any tag in an array" do
- @tagger.tag("one")
- @tagger.should_not be_tagged("two","three")
+ tagger.tag("one")
+ expect(tagger).to_not be_tagged("two","three")
+ end
+
+ context "when tagging" do
+ it "converts symbols to strings" do
+ tagger.tag(:hello)
+ expect(tagger.tags).to include('hello')
+ end
+
+ it "downcases tags" do
+ tagger.tag(:HEllO)
+ tagger.tag("GooDByE")
+ expect(tagger).to be_tagged("hello")
+ expect(tagger).to be_tagged("goodbye")
+ end
+
+ it "accepts hyphenated tags" do
+ tagger.tag("my-tag")
+ expect(tagger).to be_tagged("my-tag")
+ end
+ end
+
+ context "when querying if tagged" do
+ it "responds true if queried on the entire set" do
+ tagger.tag("one", "two")
+ expect(tagger).to be_tagged("one", "two")
+ end
+
+ it "responds true if queried on a subset" do
+ tagger.tag("one", "two", "three")
+ expect(tagger).to be_tagged("two", "one")
+ end
+
+ it "responds true if queried on an overlapping but not fully contained set" do
+ tagger.tag("one", "two")
+ expect(tagger).to be_tagged("zero", "one")
+ end
+
+ it "responds false if queried on a disjoint set" do
+ tagger.tag("one", "two", "three")
+ expect(tagger).to_not be_tagged("five")
+ end
+
+ it "responds false if queried on the empty set" do
+ expect(tagger).to_not be_tagged
+ end
+ end
+
+ context "when assigning tags" do
+ it "splits a string on ','" do
+ tagger.tags = "one, two, three"
+ expect(tagger).to be_tagged("one")
+ expect(tagger).to be_tagged("two")
+ expect(tagger).to be_tagged("three")
+ end
end
end
diff --git a/spec/unit/util/watcher_spec.rb b/spec/unit/util/watcher_spec.rb
index 64fab9681..33f75ab12 100644
--- a/spec/unit/util/watcher_spec.rb
+++ b/spec/unit/util/watcher_spec.rb
@@ -14,7 +14,10 @@ describe Puppet::Util::Watcher do
let(:filename) { "fake" }
def after_reading_the_sequence(initial, *results)
- expectation = File.stubs(:stat).with(filename)
+ mock_file = mock(filename)
+ Puppet::FileSystem::File.expects(:new).with(filename).at_least(1).returns mock_file
+
+ expectation = mock_file.stubs(:stat)
([initial] + results).each do |result|
expectation = if result.is_a? Class
expectation.raises(result)
diff --git a/spec/unit/util/windows/access_control_entry_spec.rb b/spec/unit/util/windows/access_control_entry_spec.rb
new file mode 100644
index 000000000..b139b0d42
--- /dev/null
+++ b/spec/unit/util/windows/access_control_entry_spec.rb
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+require 'spec_helper'
+require 'puppet/util/windows'
+
+describe "Puppet::Util::Windows::AccessControlEntry", :if => Puppet.features.microsoft_windows? do
+ let(:klass) { Puppet::Util::Windows::AccessControlEntry }
+ let(:sid) { 'S-1-5-18' }
+ let(:mask) { Windows::File::FILE_ALL_ACCESS }
+
+ it "creates an access allowed ace" do
+ ace = klass.new(sid, mask)
+
+ ace.type.should == klass::ACCESS_ALLOWED_ACE_TYPE
+ end
+
+ it "creates an access denied ace" do
+ ace = klass.new(sid, mask, 0, klass::ACCESS_DENIED_ACE_TYPE)
+
+ ace.type.should == klass::ACCESS_DENIED_ACE_TYPE
+ end
+
+ it "creates a non-inherited ace by default" do
+ ace = klass.new(sid, mask)
+
+ ace.should_not be_inherited
+ end
+
+ it "creates an inherited ace" do
+ ace = klass.new(sid, mask, klass::INHERITED_ACE)
+
+ ace.should be_inherited
+ end
+
+ it "creates a non-inherit-only ace by default" do
+ ace = klass.new(sid, mask)
+
+ ace.should_not be_inherit_only
+ end
+
+ it "creates an inherit-only ace" do
+ ace = klass.new(sid, mask, klass::INHERIT_ONLY_ACE)
+
+ ace.should be_inherit_only
+ end
+
+ context "when comparing aces" do
+ let(:ace1) { klass.new(sid, mask, klass::INHERIT_ONLY_ACE, klass::ACCESS_DENIED_ACE_TYPE) }
+ let(:ace2) { klass.new(sid, mask, klass::INHERIT_ONLY_ACE, klass::ACCESS_DENIED_ACE_TYPE) }
+
+ it "returns true if different objects have the same set of values" do
+ ace1.should == ace2
+ end
+
+ it "returns false if different objects have different sets of values" do
+ ace = klass.new(sid, mask)
+ ace.should_not == ace1
+ end
+
+ it "returns true when testing if two objects are eql?" do
+ ace1.eql?(ace2)
+ end
+
+ it "returns false when comparing object identity" do
+ ace1.should_not be_equal(ace2)
+ end
+ end
+end
diff --git a/spec/unit/util/windows/access_control_list_spec.rb b/spec/unit/util/windows/access_control_list_spec.rb
new file mode 100644
index 000000000..66c917b29
--- /dev/null
+++ b/spec/unit/util/windows/access_control_list_spec.rb
@@ -0,0 +1,133 @@
+#!/usr/bin/env ruby
+require 'spec_helper'
+require 'puppet/util/windows'
+
+describe "Puppet::Util::Windows::AccessControlList", :if => Puppet.features.microsoft_windows? do
+ let(:klass) { Puppet::Util::Windows::AccessControlList }
+ let(:system_sid) { 'S-1-5-18' }
+ let(:admins_sid) { 'S-1-5-544' }
+ let(:none_sid) { 'S-1-0-0' }
+
+ let(:system_ace) do
+ Puppet::Util::Windows::AccessControlEntry.new(system_sid, 0x1)
+ end
+ let(:admins_ace) do
+ Puppet::Util::Windows::AccessControlEntry.new(admins_sid, 0x2)
+ end
+ let(:none_ace) do
+ Puppet::Util::Windows::AccessControlEntry.new(none_sid, 0x3)
+ end
+
+ it "constructs an empty list" do
+ acl = klass.new
+
+ acl.to_a.should be_empty
+ end
+
+ it "supports copy constructor" do
+ aces = klass.new([system_ace]).to_a
+
+ aces.to_a.should == [system_ace]
+ end
+
+ context "appending" do
+ it "appends an allow ace" do
+ acl = klass.new
+ acl.allow(system_sid, 0x1, 0x2)
+
+ acl.first.type.should == klass::ACCESS_ALLOWED_ACE_TYPE
+ end
+
+ it "appends a deny ace" do
+ acl = klass.new
+ acl.deny(system_sid, 0x1, 0x2)
+
+ acl.first.type.should == klass::ACCESS_DENIED_ACE_TYPE
+ end
+
+ it "always appends, never overwrites an ACE" do
+ acl = klass.new([system_ace])
+ acl.allow(admins_sid, admins_ace.mask, admins_ace.flags)
+
+ aces = acl.to_a
+ aces.size.should == 2
+ aces[0].should == system_ace
+ aces[1].sid.should == admins_sid
+ aces[1].mask.should == admins_ace.mask
+ aces[1].flags.should == admins_ace.flags
+ end
+ end
+
+ context "reassigning" do
+ it "preserves the mask from the old sid when reassigning to the new sid" do
+ dacl = klass.new([system_ace])
+
+ dacl.reassign!(system_ace.sid, admins_ace.sid)
+ # we removed system, so ignore prepended ace
+ ace = dacl.to_a[1]
+ ace.sid.should == admins_sid
+ ace.mask.should == system_ace.mask
+ end
+
+ it "matches multiple sids" do
+ dacl = klass.new([system_ace, system_ace])
+
+ dacl.reassign!(system_ace.sid, admins_ace.sid)
+ # we removed system, so ignore prepended ace
+ aces = dacl.to_a
+ aces.size.should == 3
+ aces.to_a[1,2].each do |ace|
+ ace.sid.should == admins_ace.sid
+ end
+ end
+
+ it "preserves aces for sids that don't match, in their original order" do
+ dacl = klass.new([system_ace, admins_ace])
+
+ dacl.reassign!(system_sid, none_sid)
+ aces = dacl.to_a
+ aces[1].sid == admins_ace.sid
+ end
+
+ it "preserves inherited aces, even if the sids match" do
+ flags = Puppet::Util::Windows::AccessControlEntry::INHERITED_ACE
+ inherited_ace = Puppet::Util::Windows::AccessControlEntry.new(system_sid, 0x1, flags)
+ dacl = klass.new([inherited_ace, system_ace])
+ dacl.reassign!(system_sid, none_sid)
+ aces = dacl.to_a
+
+ aces[0].sid.should == system_sid
+ end
+
+ it "prepends an explicit ace for the new sid with the same mask and basic inheritance as the inherited ace" do
+ expected_flags =
+ Puppet::Util::Windows::AccessControlEntry::OBJECT_INHERIT_ACE |
+ Puppet::Util::Windows::AccessControlEntry::CONTAINER_INHERIT_ACE |
+ Puppet::Util::Windows::AccessControlEntry::INHERIT_ONLY_ACE
+
+ flags = Puppet::Util::Windows::AccessControlEntry::INHERITED_ACE | expected_flags
+
+ inherited_ace = Puppet::Util::Windows::AccessControlEntry.new(system_sid, 0x1, flags)
+ dacl = klass.new([inherited_ace])
+ dacl.reassign!(system_sid, none_sid)
+ aces = dacl.to_a
+
+ aces.size.should == 2
+ aces[0].sid.should == none_sid
+ aces[0].should_not be_inherited
+ aces[0].flags.should == expected_flags
+
+ aces[1].sid.should == system_sid
+ aces[1].should be_inherited
+ end
+
+ it "makes a copy of the ace prior to modifying it" do
+ arr = [system_ace]
+
+ acl = klass.new(arr)
+ acl.reassign!(system_sid, none_sid)
+
+ arr[0].sid.should == system_sid
+ end
+ end
+end
diff --git a/spec/unit/util/windows/root_certs_spec.rb b/spec/unit/util/windows/root_certs_spec.rb
index 155707e4e..6b1d9891e 100755
--- a/spec/unit/util/windows/root_certs_spec.rb
+++ b/spec/unit/util/windows/root_certs_spec.rb
@@ -3,13 +3,15 @@ require 'spec_helper'
require 'puppet/util/windows'
describe "Puppet::Util::Windows::RootCerts", :if => Puppet::Util::Platform.windows? do
- let(:klass) { Puppet::Util::Windows::RootCerts }
- let(:x509) { 'mycert' }
-
- context '#each' do
- it "should enumerate each root cert" do
- klass.expects(:load_certs).returns([x509])
- klass.instance.to_a.should == [x509]
- end
+ let(:x509_store) { Puppet::Util::Windows::RootCerts.instance.to_a }
+
+ it "should return at least one X509 certificate" do
+ expect(x509_store.to_a).to have_at_least(1).items
+ end
+
+ it "should return an X509 certificate with a subject" do
+ x509 = x509_store.first
+
+ expect(x509.subject.to_s).to match(/CN=.*/)
end
end
diff --git a/spec/unit/util/windows/security_descriptor_spec.rb b/spec/unit/util/windows/security_descriptor_spec.rb
new file mode 100644
index 000000000..61db2f598
--- /dev/null
+++ b/spec/unit/util/windows/security_descriptor_spec.rb
@@ -0,0 +1,117 @@
+#!/usr/bin/env ruby
+
+require 'spec_helper'
+require 'puppet/util/windows'
+
+describe "Puppet::Util::Windows::SecurityDescriptor", :if => Puppet.features.microsoft_windows? do
+ let(:system_sid) { Win32::Security::SID::LocalSystem }
+ let(:admins_sid) { Win32::Security::SID::BuiltinAdministrators }
+ let(:group_sid) { Win32::Security::SID::Nobody }
+ let(:new_sid) { 'S-1-5-32-500-1-2-3' }
+
+ def empty_dacl
+ Puppet::Util::Windows::AccessControlList.new
+ end
+
+ def system_ace_dacl
+ dacl = Puppet::Util::Windows::AccessControlList.new
+ dacl.allow(system_sid, 0x1)
+ dacl
+ end
+
+ context "owner" do
+ it "changes the owner" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(system_sid, group_sid, system_ace_dacl)
+ sd.owner = new_sid
+
+ sd.owner.should == new_sid
+ end
+
+ it "performs a noop if the new owner is the same as the old one" do
+ dacl = system_ace_dacl
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(system_sid, group_sid, dacl)
+ sd.owner = sd.owner
+
+ sd.dacl.object_id.should == dacl.object_id
+ end
+
+ it "prepends SYSTEM when security descriptor owner is no longer SYSTEM" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(system_sid, group_sid, system_ace_dacl)
+ sd.owner = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 2
+ aces[0].sid.should == system_sid
+ aces[1].sid.should == new_sid
+ end
+
+ it "does not prepend SYSTEM when DACL already contains inherited SYSTEM ace" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(admins_sid, system_sid, empty_dacl)
+ sd.dacl.allow(admins_sid, 0x1)
+ sd.dacl.allow(system_sid, 0x1, Puppet::Util::Windows::AccessControlEntry::INHERITED_ACE)
+ sd.owner = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 2
+ aces[0].sid.should == new_sid
+ end
+
+ it "does not prepend SYSTEM when security descriptor owner wasn't SYSTEM" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(group_sid, group_sid, empty_dacl)
+ sd.dacl.allow(group_sid, 0x1)
+ sd.owner = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 1
+ aces[0].sid.should == new_sid
+ end
+ end
+
+ context "group" do
+ it "changes the group" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(system_sid, group_sid, system_ace_dacl)
+ sd.group = new_sid
+
+ sd.group.should == new_sid
+ end
+
+ it "performs a noop if the new group is the same as the old one" do
+ dacl = system_ace_dacl
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(system_sid, group_sid, dacl)
+ sd.group = sd.group
+
+ sd.dacl.object_id.should == dacl.object_id
+ end
+
+ it "prepends SYSTEM when security descriptor group is no longer SYSTEM" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(new_sid, system_sid, system_ace_dacl)
+ sd.group = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 2
+ aces[0].sid.should == system_sid
+ aces[1].sid.should == new_sid
+ end
+
+ it "does not prepend SYSTEM when DACL already contains inherited SYSTEM ace" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(admins_sid, admins_sid, empty_dacl)
+ sd.dacl.allow(admins_sid, 0x1)
+ sd.dacl.allow(system_sid, 0x1, Puppet::Util::Windows::AccessControlEntry::INHERITED_ACE)
+ sd.group = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 2
+ aces[0].sid.should == new_sid
+ end
+
+ it "does not prepend SYSTEM when security descriptor group wasn't SYSTEM" do
+ sd = Puppet::Util::Windows::SecurityDescriptor.new(group_sid, group_sid, empty_dacl)
+ sd.dacl.allow(group_sid, 0x1)
+ sd.group = new_sid
+
+ aces = sd.dacl.to_a
+ aces.size.should == 1
+ aces[0].sid.should == new_sid
+ end
+ end
+end
diff --git a/spec/unit/util/windows/sid_spec.rb b/spec/unit/util/windows/sid_spec.rb
index d53e93ae6..770512188 100755
--- a/spec/unit/util/windows/sid_spec.rb
+++ b/spec/unit/util/windows/sid_spec.rb
@@ -15,6 +15,45 @@ describe "Puppet::Util::Windows::SID", :if => Puppet.features.microsoft_windows?
let(:unknown_sid) { 'S-0-0-0' }
let(:unknown_name) { 'chewbacca' }
+ context "#octet_string_to_sid_object" do
+ it "should properly convert an array of bytes for the local Administrator SID" do
+ host = '.'
+ username = 'Administrator'
+ admin = WIN32OLE.connect("WinNT://#{host}/#{username},user")
+ converted = subject.octet_string_to_sid_object(admin.objectSID)
+
+ converted.should == Win32::Security::SID.new(username, host)
+ converted.should be_an_instance_of Win32::Security::SID
+ end
+
+ it "should properly convert an array of bytes for a well-known SID" do
+ bytes = [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0]
+ converted = subject.octet_string_to_sid_object(bytes)
+
+ converted.should == Win32::Security::SID.new('SYSTEM')
+ converted.should be_an_instance_of Win32::Security::SID
+ end
+
+ it "should raise an error for non-array input" do
+ expect {
+ subject.octet_string_to_sid_object(invalid_sid)
+ }.to raise_error(Puppet::Error, /Octet string must be an array of bytes/)
+ end
+
+ it "should raise an error for an empty byte array" do
+ expect {
+ subject.octet_string_to_sid_object([])
+ }.to raise_error(Puppet::Error, /Octet string must be an array of bytes/)
+ end
+
+ it "should raise an error for a malformed byte array" do
+ expect {
+ invalid_octet = [1]
+ subject.octet_string_to_sid_object(invalid_octet)
+ }.to raise_error(Win32::Security::SID::Error, /No mapping between account names and security IDs was done./)
+ end
+ end
+
context "#name_to_sid" do
it "should return nil if the account does not exist" do
subject.name_to_sid(unknown_name).should be_nil
@@ -28,6 +67,10 @@ describe "Puppet::Util::Windows::SID", :if => Puppet.features.microsoft_windows?
subject.name_to_sid('SYSTEM').should == subject.name_to_sid('system')
end
+ it "should be leading and trailing whitespace-insensitive" do
+ subject.name_to_sid('SYSTEM').should == subject.name_to_sid(' SYSTEM ')
+ end
+
it "should accept domain qualified account names" do
subject.name_to_sid('NT AUTHORITY\SYSTEM').should == sid
end
@@ -37,6 +80,32 @@ describe "Puppet::Util::Windows::SID", :if => Puppet.features.microsoft_windows?
end
end
+ context "#name_to_sid_object" do
+ it "should return nil if the account does not exist" do
+ subject.name_to_sid_object(unknown_name).should be_nil
+ end
+
+ it "should return a Win32::Security::SID instance for any valid sid" do
+ subject.name_to_sid_object(sid).should be_an_instance_of(Win32::Security::SID)
+ end
+
+ it "should accept unqualified account name" do
+ subject.name_to_sid_object('SYSTEM').to_s.should == sid
+ end
+
+ it "should be case-insensitive" do
+ subject.name_to_sid_object('SYSTEM').should == subject.name_to_sid_object('system')
+ end
+
+ it "should be leading and trailing whitespace-insensitive" do
+ subject.name_to_sid_object('SYSTEM').should == subject.name_to_sid_object(' SYSTEM ')
+ end
+
+ it "should accept domain qualified account names" do
+ subject.name_to_sid_object('NT AUTHORITY\SYSTEM').to_s.should == sid
+ end
+ end
+
context "#sid_to_name" do
it "should return nil if given a sid for an account that doesn't exist" do
subject.sid_to_name(unknown_sid).should be_nil
diff --git a/spec/unit/util/yaml_spec.rb b/spec/unit/util/yaml_spec.rb
index 960388ade..978afb0a2 100644
--- a/spec/unit/util/yaml_spec.rb
+++ b/spec/unit/util/yaml_spec.rb
@@ -33,6 +33,20 @@ describe Puppet::Util::Yaml do
expect { Puppet::Util::Yaml.load_file("not\0allowed") }.to raise_error(Puppet::Util::Yaml::YamlLoadError, /null byte/)
end
+ context "when the file is empty" do
+ it "returns false" do
+ Puppet::FileSystem::File.new(filename).touch
+
+ expect(Puppet::Util::Yaml.load_file(filename)).to be_false
+ end
+
+ it "allows return value to be overridden" do
+ Puppet::FileSystem::File.new(filename).touch
+
+ expect(Puppet::Util::Yaml.load_file(filename, {})).to eq({})
+ end
+ end
+
def write_file(name, contents)
File.open(name, "w") do |fh|
fh.write(contents)
diff --git a/spec/unit/util_spec.rb b/spec/unit/util_spec.rb
index 48b6e6fc5..58cc4bbd8 100755
--- a/spec/unit/util_spec.rb
+++ b/spec/unit/util_spec.rb
@@ -19,7 +19,7 @@ describe Puppet::Util do
end
def get_mode(file)
- File.lstat(file).mode & 07777
+ Puppet::FileSystem::File.new(file).lstat.mode & 07777
end
end
@@ -449,7 +449,7 @@ describe Puppet::Util do
it "should copy the permissions of the source file before yielding on Unix", :if => !Puppet.features.microsoft_windows? do
set_mode(0555, target.path)
- inode = File.stat(target.path).ino
+ inode = Puppet::FileSystem::File.new(target.path).stat.ino
yielded = false
subject.replace_file(target.path, 0600) do |fh|
@@ -458,19 +458,19 @@ describe Puppet::Util do
end
yielded.should be_true
- File.stat(target.path).ino.should_not == inode
+ Puppet::FileSystem::File.new(target.path).stat.ino.should_not == inode
get_mode(target.path).should == 0555
end
it "should use the default permissions if the source file doesn't exist" do
new_target = target.path + '.foo'
- File.should_not be_exist(new_target)
+ Puppet::FileSystem::File.exist?(new_target).should be_false
begin
subject.replace_file(new_target, 0555) {|fh| fh.puts "foo" }
get_mode(new_target).should == 0555
ensure
- File.unlink(new_target) if File.exists?(new_target)
+ Puppet::FileSystem::File.unlink(new_target) if Puppet::FileSystem::File.exist?(new_target)
end
end
@@ -502,14 +502,14 @@ describe Puppet::Util do
{:string => '664', :number => 0664, :symbolic => "ug=rw-,o=r--" }.each do |label,mode|
it "should support #{label} format permissions" do
new_target = target.path + "#{mode}.foo"
- File.should_not be_exist(new_target)
+ Puppet::FileSystem::File.exist?(new_target).should be_false
begin
subject.replace_file(new_target, mode) {|fh| fh.puts "this is an interesting content" }
get_mode(new_target).should == 0664
ensure
- File.unlink(new_target) if File.exists?(new_target)
+ Puppet::FileSystem::File.unlink(new_target) if Puppet::FileSystem::File.exist?(new_target)
end
end
end