summaryrefslogtreecommitdiff
path: root/spec/unit
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit')
-rw-r--r--spec/unit/audit/audit_reporter_spec.rb64
-rw-r--r--spec/unit/chef_fs/file_pattern_spec.rb18
-rw-r--r--spec/unit/client_spec.rb432
-rw-r--r--spec/unit/cookbook_spec.rb9
-rw-r--r--spec/unit/cookbook_version_spec.rb20
-rw-r--r--spec/unit/deprecation_spec.rb55
-rw-r--r--spec/unit/exceptions_spec.rb4
-rw-r--r--spec/unit/formatters/doc_spec.rb46
-rw-r--r--spec/unit/knife/core/subcommand_loader_spec.rb22
-rw-r--r--spec/unit/knife/core/ui_spec.rb14
-rw-r--r--spec/unit/mixin/command_spec.rb3
-rw-r--r--spec/unit/mixin/powershell_out_spec.rb70
-rw-r--r--spec/unit/provider/directory_spec.rb334
-rw-r--r--spec/unit/provider/ifconfig/debian_spec.rb10
-rw-r--r--spec/unit/provider/package/openbsd_spec.rb21
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb4
-rw-r--r--spec/unit/provider/powershell_spec.rb64
-rw-r--r--spec/unit/provider/remote_directory_spec.rb4
-rw-r--r--spec/unit/provider/service/freebsd_service_spec.rb12
-rw-r--r--spec/unit/provider/user_spec.rb6
-rw-r--r--spec/unit/resource/template_spec.rb2
-rw-r--r--spec/unit/resource_spec.rb12
22 files changed, 593 insertions, 633 deletions
diff --git a/spec/unit/audit/audit_reporter_spec.rb b/spec/unit/audit/audit_reporter_spec.rb
index 4bf889510a..75c96155da 100644
--- a/spec/unit/audit/audit_reporter_spec.rb
+++ b/spec/unit/audit/audit_reporter_spec.rb
@@ -88,6 +88,29 @@ describe Chef::Audit::AuditReporter do
reporter.run_completed(node)
end
+ context "when audit phase failed" do
+
+ let(:audit_error) { double("AuditError", :class => "Chef::Exceptions::AuditError",
+ :message => "Audit phase failed with error message: derpderpderp",
+ :backtrace => ["/path/recipe.rb:57", "/path/library.rb:106"]) }
+
+ before do
+ reporter.instance_variable_set(:@audit_phase_error, audit_error)
+ end
+
+ it "reports an error" do
+ reporter.run_completed(node)
+ expect(run_data).to have_key(:error)
+ expect(run_data).to have_key(:error)
+ expect(run_data[:error]).to eq <<-EOM.strip!
+Chef::Exceptions::AuditError: Audit phase failed with error message: derpderpderp
+/path/recipe.rb:57
+/path/library.rb:106
+EOM
+ end
+
+ end
+
context "when unable to post to server" do
let(:error) do
@@ -215,9 +238,13 @@ describe Chef::Audit::AuditReporter do
let(:audit_data) { Chef::Audit::AuditData.new(node.name, run_id) }
let(:run_data) { audit_data.to_hash }
- let(:error) { double("AuditError", :class => "Chef::Exception::AuditError",
- :message => "Well that certainly didn't work",
- :backtrace => ["line 0", "line 1", "line 2"]) }
+ let(:audit_error) { double("AuditError", :class => "Chef::Exceptions::AuditError",
+ :message => "Audit phase failed with error message: derpderpderp",
+ :backtrace => ["/path/recipe.rb:57", "/path/library.rb:106"]) }
+
+ let(:run_error) { double("RunError", :class => "Chef::Exceptions::RunError",
+ :message => "This error shouldn't be reported.",
+ :backtrace => ["fix it", "fix it", "fix it"]) }
before do
allow(reporter).to receive(:auditing_enabled?).and_return(true)
@@ -226,15 +253,32 @@ describe Chef::Audit::AuditReporter do
allow(audit_data).to receive(:to_hash).and_return(run_data)
end
- it "adds the error information to the reported data" do
- expect(rest).to receive(:create_url)
- expect(rest).to receive(:post)
- reporter.run_failed(error)
- expect(run_data).to have_key(:error)
- expect(run_data[:error]).to eq "Chef::Exception::AuditError: Well that certainly didn't work\n" +
- "line 0\nline 1\nline 2"
+ context "when no prior exception is stored" do
+ it "reports no error" do
+ expect(rest).to receive(:create_url)
+ expect(rest).to receive(:post)
+ reporter.run_failed(run_error)
+ expect(run_data).to_not have_key(:error)
+ end
end
+ context "when some prior exception is stored" do
+ before do
+ reporter.instance_variable_set(:@audit_phase_error, audit_error)
+ end
+
+ it "reports the prior error" do
+ expect(rest).to receive(:create_url)
+ expect(rest).to receive(:post)
+ reporter.run_failed(run_error)
+ expect(run_data).to have_key(:error)
+ expect(run_data[:error]).to eq <<-EOM.strip!
+Chef::Exceptions::AuditError: Audit phase failed with error message: derpderpderp
+/path/recipe.rb:57
+/path/library.rb:106
+EOM
+ end
+ end
end
shared_context "audit data" do
diff --git a/spec/unit/chef_fs/file_pattern_spec.rb b/spec/unit/chef_fs/file_pattern_spec.rb
index a9f06e8424..ed5f314605 100644
--- a/spec/unit/chef_fs/file_pattern_spec.rb
+++ b/spec/unit/chef_fs/file_pattern_spec.rb
@@ -157,7 +157,7 @@ describe Chef::ChefFS::FilePattern do
end
end
- context 'with simple pattern "a\*\b"', :pending => (Chef::Platform.windows?) do
+ context 'with simple pattern "a\*\b"', :skip => (Chef::Platform.windows?) do
let(:pattern) { Chef::ChefFS::FilePattern.new('a\*\b') }
it 'match?' do
expect(pattern.match?('a*b')).to be_truthy
@@ -264,7 +264,7 @@ describe Chef::ChefFS::FilePattern do
end
end
- context 'with star pattern "/abc/d[a-z][0-9]f/ghi"', :pending => (Chef::Platform.windows?) do
+ context 'with star pattern "/abc/d[a-z][0-9]f/ghi"', :skip => (Chef::Platform.windows?) do
let(:pattern) { Chef::ChefFS::FilePattern.new('/abc/d[a-z][0-9]f/ghi') }
it 'match?' do
expect(pattern.match?('/abc/de1f/ghi')).to be_truthy
@@ -352,11 +352,7 @@ describe Chef::ChefFS::FilePattern do
expect(pattern.could_match_children?('/abc/def/ghi')).to be_truthy
expect(pattern.could_match_children?('abc')).to be_falsey
end
- it 'could_match_children? /abc** returns false for /xyz' do
- pending 'Make could_match_children? more rigorous'
- # At the moment, we return false for this, but in the end it would be nice to return true:
- expect(pattern.could_match_children?('/xyz')).to be_falsey
- end
+
it 'exact_child_name_under' do
expect(pattern.exact_child_name_under('/')).to eq(nil)
expect(pattern.exact_child_name_under('/abc')).to eq(nil)
@@ -440,14 +436,6 @@ describe Chef::ChefFS::FilePattern do
expect(p('/.').exact_path).to eq('/')
expect(p('/.').match?('/')).to be_truthy
end
- it 'handles dot by itself', :pending => "decide what to do with dot by itself" do
- expect(p('.').normalized_pattern).to eq('.')
- expect(p('.').exact_path).to eq('.')
- expect(p('.').match?('.')).to be_truthy
- expect(p('./').normalized_pattern).to eq('.')
- expect(p('./').exact_path).to eq('.')
- expect(p('./').match?('.')).to be_truthy
- end
it 'handles dotdot' do
expect(p('abc/../def').normalized_pattern).to eq('def')
expect(p('abc/../def').exact_path).to eq('def')
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb
index d8c4ede796..1e4bbb5c56 100644
--- a/spec/unit/client_spec.rb
+++ b/spec/unit/client_spec.rb
@@ -19,6 +19,8 @@
#
require 'spec_helper'
+require 'spec/support/shared/context/client'
+require 'spec/support/shared/examples/client'
require 'chef/run_context'
require 'chef/rest'
@@ -28,55 +30,7 @@ class FooError < RuntimeError
end
describe Chef::Client do
-
- let(:hostname) { "hostname" }
- let(:machinename) { "machinename.example.org" }
- let(:fqdn) { "hostname.example.org" }
-
- let(:ohai_data) do
- { :fqdn => fqdn,
- :hostname => hostname,
- :machinename => machinename,
- :platform => 'example-platform',
- :platform_version => 'example-platform-1.0',
- :data => {}
- }
- end
-
- let(:ohai_system) do
- ohai_system = double( "Ohai::System",
- :all_plugins => true,
- :data => ohai_data)
- allow(ohai_system).to receive(:[]) do |key|
- ohai_data[key]
- end
- ohai_system
- end
-
- let(:node) do
- Chef::Node.new.tap do |n|
- n.name(fqdn)
- n.chef_environment("_default")
- end
- end
-
- let(:json_attribs) { nil }
- let(:client_opts) { {} }
-
- let(:client) do
- Chef::Config[:event_loggers] = []
- Chef::Client.new(json_attribs, client_opts).tap do |c|
- c.node = node
- end
- end
-
- before do
- Chef::Log.logger = Logger.new(StringIO.new)
-
- # Node/Ohai data
- #Chef::Config[:node_name] = fqdn
- allow(Ohai::System).to receive(:new).and_return(ohai_system)
- end
+ include_context "client"
context "when minimal ohai is configured" do
before do
@@ -88,7 +42,6 @@ describe Chef::Client do
expect(ohai_system).to receive(:all_plugins).with(expected_filter)
client.run_ohai
end
-
end
describe "authentication protocol selection" do
@@ -117,7 +70,6 @@ describe Chef::Client do
describe "configuring output formatters" do
context "when no formatter has been configured" do
-
context "and STDOUT is a TTY" do
before do
allow(STDOUT).to receive(:tty?).and_return(true)
@@ -203,135 +155,12 @@ describe Chef::Client do
end
describe "a full client run" do
- shared_context "a client run" do
- let(:http_node_load) { double("Chef::REST (node)") }
- let(:http_cookbook_sync) { double("Chef::REST (cookbook sync)") }
- let(:http_node_save) { double("Chef::REST (node save)") }
- let(:runner) { double("Chef::Runner") }
- let(:audit_runner) { instance_double("Chef::Audit::Runner", :failed? => false) }
-
- let(:api_client_exists?) { false }
-
- let(:stdout) { StringIO.new }
- let(:stderr) { StringIO.new }
-
- let(:enable_fork) { false }
-
- def stub_for_register
- # --Client.register
- # Make sure Client#register thinks the client key doesn't
- # exist, so it tries to register and create one.
- allow(File).to receive(:exists?).and_call_original
- expect(File).to receive(:exists?).
- with(Chef::Config[:client_key]).
- exactly(:once).
- and_return(api_client_exists?)
-
- unless api_client_exists?
- # Client.register will register with the validation client name.
- expect_any_instance_of(Chef::ApiClient::Registration).to receive(:run)
- end
- end
-
- def stub_for_node_load
- # Client.register will then turn around create another
- # Chef::REST object, this time with the client key it got from the
- # previous step.
- expect(Chef::REST).to receive(:new).
- with(Chef::Config[:chef_server_url], fqdn, Chef::Config[:client_key]).
- exactly(:once).
- and_return(http_node_load)
-
- # --Client#build_node
- # looks up the node, which we will return, then later saves it.
- expect(Chef::Node).to receive(:find_or_create).with(fqdn).and_return(node)
-
- # --ResourceReporter#node_load_completed
- # gets a run id from the server for storing resource history
- # (has its own tests, so stubbing it here.)
- expect_any_instance_of(Chef::ResourceReporter).to receive(:node_load_completed)
- end
-
- def stub_for_sync_cookbooks
- # --Client#setup_run_context
- # ---Client#sync_cookbooks -- downloads the list of cookbooks to sync
- #
- expect_any_instance_of(Chef::CookbookSynchronizer).to receive(:sync_cookbooks)
- expect(Chef::REST).to receive(:new).with(Chef::Config[:chef_server_url]).and_return(http_cookbook_sync)
- expect(http_cookbook_sync).to receive(:post).
- with("environments/_default/cookbook_versions", {:run_list => []}).
- and_return({})
- end
-
- def stub_for_converge
- # --Client#converge
- expect(Chef::Runner).to receive(:new).and_return(runner)
- expect(runner).to receive(:converge).and_return(true)
- end
-
- def stub_for_audit
- # -- Client#run_audits
- expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner)
- expect(audit_runner).to receive(:run).and_return(true)
- end
-
- def stub_for_node_save
- allow(node).to receive(:data_for_save).and_return(node.for_json)
-
- # --Client#save_updated_node
- expect(Chef::REST).to receive(:new).with(Chef::Config[:chef_server_url], fqdn, Chef::Config[:client_key], validate_utf8: false).and_return(http_node_save)
- expect(http_node_save).to receive(:put_rest).with("nodes/#{fqdn}", node.for_json).and_return(true)
- end
-
- def stub_for_run
- expect_any_instance_of(Chef::RunLock).to receive(:acquire)
- expect_any_instance_of(Chef::RunLock).to receive(:save_pid)
- expect_any_instance_of(Chef::RunLock).to receive(:release)
-
- # Post conditions: check that node has been filled in correctly
- expect(client).to receive(:run_started)
- expect(client).to receive(:run_completed_successfully)
-
- # --ResourceReporter#run_completed
- # updates the server with the resource history
- # (has its own tests, so stubbing it here.)
- expect_any_instance_of(Chef::ResourceReporter).to receive(:run_completed)
- # --AuditReporter#run_completed
- # posts the audit data to server.
- # (has its own tests, so stubbing it here.)
- expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_completed)
- end
-
- before do
- Chef::Config[:client_fork] = enable_fork
- Chef::Config[:cache_path] = windows? ? 'C:\chef' : '/var/chef'
- Chef::Config[:why_run] = false
- Chef::Config[:audit_mode] = :enabled
-
- stub_const("Chef::Client::STDOUT_FD", stdout)
- stub_const("Chef::Client::STDERR_FD", stderr)
-
- stub_for_register
- stub_for_node_load
- stub_for_sync_cookbooks
- stub_for_converge
- stub_for_audit
- stub_for_node_save
- stub_for_run
- end
- end
-
shared_examples_for "a successful client run" do
include_context "a client run"
+ include_context "converge completed"
+ include_context "audit phase completed"
- it "runs ohai, sets up authentication, loads node state, synchronizes policy, converges, and runs audits" do
- # This is what we're testing.
- client.run
-
- # fork is stubbed, so we can see the outcome of the run
- expect(node.automatic_attrs[:platform]).to eq("example-platform")
- expect(node.automatic_attrs[:platform_version]).to eq("example-platform-1.0")
- end
+ include_examples "a completed run"
end
describe "when running chef-client without fork" do
@@ -339,24 +168,19 @@ describe Chef::Client do
end
describe "when the client key already exists" do
- let(:api_client_exists?) { true }
- include_examples "a successful client run"
+ include_examples "a successful client run" do
+ let(:api_client_exists?) { true }
+ end
end
- describe "when an override run list is given" do
- let(:client_opts) { {:override_runlist => "recipe[override_recipe]"} }
-
- it "should permit spaces in overriding run list" do
+ context "when an override run list is given" do
+ it "permits spaces in overriding run list" do
Chef::Client.new(nil, :override_runlist => 'role[a], role[b]')
end
- describe "when running the client" do
+ describe "calling run" do
include_examples "a successful client run" do
-
- before do
- # Client will try to compile and run override_recipe
- expect_any_instance_of(Chef::RunContext::CookbookCompiler).to receive(:compile)
- end
+ let(:client_opts) { {:override_runlist => "recipe[override_recipe]"} }
def stub_for_sync_cookbooks
# --Client#setup_run_context
@@ -373,13 +197,22 @@ describe Chef::Client do
# Expect NO node save
expect(node).not_to receive(:save)
end
+
+ before do
+ # Client will try to compile and run override_recipe
+ expect_any_instance_of(Chef::RunContext::CookbookCompiler).to receive(:compile)
+ end
end
end
end
describe "when a permanent run list is passed as an option" do
- include_examples "a successful client run" do
+ it "sets the new run list on the node" do
+ client.run
+ expect(node.run_list).to eq(Chef::RunList.new(new_runlist))
+ end
+ include_examples "a successful client run" do
let(:new_runlist) { "recipe[new_run_list_recipe]" }
let(:client_opts) { {:runlist => new_runlist} }
@@ -399,214 +232,61 @@ describe Chef::Client do
# do not create a fixture for this.
expect_any_instance_of(Chef::RunContext::CookbookCompiler).to receive(:compile)
end
-
- it "sets the new run list on the node" do
- client.run
- expect(node.run_list).to eq(Chef::RunList.new(new_runlist))
- end
end
end
- describe "when converge fails" do
- include_context "a client run" do
- let(:e) { Exception.new }
- def stub_for_converge
- expect(Chef::Runner).to receive(:new).and_return(runner)
- expect(runner).to receive(:converge).and_raise(e)
- expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError)
- end
-
- def stub_for_node_save
- expect(client).to_not receive(:save_updated_node)
- end
-
- def stub_for_run
- expect_any_instance_of(Chef::RunLock).to receive(:acquire)
- expect_any_instance_of(Chef::RunLock).to receive(:save_pid)
- expect_any_instance_of(Chef::RunLock).to receive(:release)
-
- # Post conditions: check that node has been filled in correctly
- expect(client).to receive(:run_started)
- expect(client).to receive(:run_failed)
-
- expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed)
- expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed)
- end
- end
+ describe "when converge completes successfully" do
+ include_context "a client run"
+ include_context "converge completed"
- it "runs the audits and raises the error" do
- expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error|
- expect(error.wrapped_errors.size).to eq(1)
- expect(error.wrapped_errors[0]).to eq(e)
+ describe "when audit phase errors" do
+ include_context "audit phase failed with error"
+ include_examples "a completed run with audit failure" do
+ let(:run_errors) { [audit_error] }
end
end
- end
-
- describe "when the audit phase fails" do
- context "with an exception" do
- context "when audit mode is enabled" do
- include_context "a client run" do
- let(:e) { Exception.new }
- def stub_for_audit
- expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner)
- expect(audit_runner).to receive(:run).and_raise(e)
- expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError)
- end
-
- def stub_for_run
- expect_any_instance_of(Chef::RunLock).to receive(:acquire)
- expect_any_instance_of(Chef::RunLock).to receive(:save_pid)
- expect_any_instance_of(Chef::RunLock).to receive(:release)
-
- # Post conditions: check that node has been filled in correctly
- expect(client).to receive(:run_started)
- expect(client).to receive(:run_failed)
-
- expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed)
- expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed)
- end
- end
-
- it "should save the node after converge and raise exception" do
- expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error|
- expect(error.wrapped_errors.size).to eq(1)
- expect(error.wrapped_errors[0]).to eq(e)
- end
- end
- end
-
- context "when audit mode is disabled" do
- include_context "a client run" do
- before do
- Chef::Config[:audit_mode] = :disabled
- end
-
- let(:e) { FooError.new }
-
- def stub_for_audit
- expect(Chef::Audit::Runner).to_not receive(:new)
- end
-
- def stub_for_converge
- expect(Chef::Runner).to receive(:new).and_return(runner)
- expect(runner).to receive(:converge).and_raise(e)
- expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(FooError)
- end
-
- def stub_for_node_save
- expect(client).to_not receive(:save_updated_node)
- end
-
- def stub_for_run
- expect_any_instance_of(Chef::RunLock).to receive(:acquire)
- expect_any_instance_of(Chef::RunLock).to receive(:save_pid)
- expect_any_instance_of(Chef::RunLock).to receive(:release)
-
-
- # Post conditions: check that node has been filled in correctly
- expect(client).to receive(:run_started)
- expect(client).to receive(:run_failed)
-
- expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed)
-
- end
-
- it "re-raises an unwrapped exception" do
- expect { client.run }.to raise_error(FooError)
- end
- end
- end
-
+ describe "when audit phase completed" do
+ include_context "audit phase completed"
+ include_examples "a completed run"
end
- context "with failed audits" do
- include_context "a client run" do
- let(:audit_runner) do
- instance_double("Chef::Audit::Runner", :run => true, :failed? => true, :num_failed => 1, :num_total => 1)
- end
-
- def stub_for_audit
- expect(Chef::Audit::Runner).to receive(:new).and_return(audit_runner)
- expect(Chef::Application).to receive(:debug_stacktrace).with an_instance_of(Chef::Exceptions::RunFailedWrappingError)
- end
-
- def stub_for_run
- expect_any_instance_of(Chef::RunLock).to receive(:acquire)
- expect_any_instance_of(Chef::RunLock).to receive(:save_pid)
- expect_any_instance_of(Chef::RunLock).to receive(:release)
-
- # Post conditions: check that node has been filled in correctly
- expect(client).to receive(:run_started)
- expect(client).to receive(:run_failed)
-
- expect_any_instance_of(Chef::ResourceReporter).to receive(:run_failed)
- expect_any_instance_of(Chef::Audit::AuditReporter).to receive(:run_failed)
- end
- end
-
- it "should save the node after converge and raise exception" do
- expect{ client.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error|
- expect(error.wrapped_errors.size).to eq(1)
- expect(error.wrapped_errors[0]).to be_instance_of(Chef::Exceptions::AuditsFailed)
- end
+ describe "when audit phase completed with failed controls" do
+ include_context "audit phase completed with failed controls"
+ include_examples "a completed run with audit failure" do
+ let(:run_errors) { [audit_error] }
end
end
end
- describe "when why_run mode is enabled" do
- include_context "a client run" do
-
- before do
- Chef::Config[:why_run] = true
- end
-
- def stub_for_audit
- expect(Chef::Audit::Runner).to_not receive(:new)
- end
-
- def stub_for_node_save
- # This is how we should be mocking external calls - not letting it fall all the way through to the
- # REST call
- expect(node).to receive(:save)
- end
-
- it "runs successfully without enabling the audit runner" do
- client.run
+ describe "when converge errors" do
+ include_context "a client run"
+ include_context "converge failed"
- # fork is stubbed, so we can see the outcome of the run
- expect(node.automatic_attrs[:platform]).to eq("example-platform")
- expect(node.automatic_attrs[:platform_version]).to eq("example-platform-1.0")
+ describe "when audit phase errors" do
+ include_context "audit phase failed with error"
+ include_examples "a failed run" do
+ let(:run_errors) { [converge_error, audit_error] }
end
end
- end
-
- describe "when audits are disabled" do
- include_context "a client run" do
-
- before do
- Chef::Config[:audit_mode] = :disabled
- end
- def stub_for_audit
- expect(Chef::Audit::Runner).to_not receive(:new)
+ describe "when audit phase completed" do
+ include_context "audit phase completed"
+ include_examples "a failed run" do
+ let(:run_errors) { [converge_error] }
end
+ end
- it "runs successfully without enabling the audit runner" do
- client.run
-
- # fork is stubbed, so we can see the outcome of the run
- expect(node.automatic_attrs[:platform]).to eq("example-platform")
- expect(node.automatic_attrs[:platform_version]).to eq("example-platform-1.0")
+ describe "when audit phase completed with failed controls" do
+ include_context "audit phase completed with failed controls"
+ include_examples "a failed run" do
+ let(:run_errors) { [converge_error, audit_error] }
end
end
end
-
end
-
describe "when handling run failures" do
-
it "should remove the run_lock on failure of #load_node" do
@run_lock = double("Chef::RunLock", :acquire => true)
allow(Chef::RunLock).to receive(:new).and_return(@run_lock)
@@ -779,6 +459,7 @@ describe Chef::Client do
Chef::Config[:solo] = true
Chef::Config[:cookbook_path] = ["/path/to/invalid/cookbook_path"]
end
+
context "when any directory of cookbook_path contains no cookbook" do
it "raises CookbookNotFound error" do
expect do
@@ -833,7 +514,10 @@ describe Chef::Client do
it "should run exception handlers on early fail" do
expect(subject).to receive(:run_failed)
- expect { subject.run }.to raise_error(NoMethodError)
+ expect { subject.run }.to raise_error(Chef::Exceptions::RunFailedWrappingError) do |error|
+ expect(error.wrapped_errors.size).to eq 1
+ expect(error.wrapped_errors).to include(NoMethodError)
+ end
end
end
end
diff --git a/spec/unit/cookbook_spec.rb b/spec/unit/cookbook_spec.rb
index 7b3cda2af1..f36b031309 100644
--- a/spec/unit/cookbook_spec.rb
+++ b/spec/unit/cookbook_spec.rb
@@ -59,15 +59,6 @@ describe Chef::CookbookVersion do
expect(@cookbook.fully_qualified_recipe_names.include?("openldap::three")).to eq(true)
end
- it "should find a preferred file" do
- skip
- end
-
- it "should not return an unchanged preferred file" do
- pending
- expect(@cookbook.preferred_filename(@node, :files, 'a-filename', 'the-checksum')).to be_nil
- end
-
it "should raise an ArgumentException if you try to load a bad recipe name" do
expect { @cookbook.load_recipe("doesnt_exist", @node) }.to raise_error(ArgumentError)
end
diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb
index 440dd9da6c..4990aef004 100644
--- a/spec/unit/cookbook_version_spec.rb
+++ b/spec/unit/cookbook_version_spec.rb
@@ -306,26 +306,6 @@ describe Chef::CookbookVersion do
subject(:cbv) { Chef::CookbookVersion.new("version validation", '/tmp/blah') }
- describe "HTTP Resource behaviors", pending: "will be deprected when CookbookManifest API is stablized" do
-
- it "errors on #save_url" do
- expect { cbv.save_url }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- end
-
- it "errors on #force_save_url" do
- expect { cbv.force_save_url }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- end
-
- it "errors on #to_hash" do
- expect { cbv.to_hash }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- end
-
- it "errors on #to_json" do
- expect { cbv.to_json }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
- end
-
- end
-
it "errors on #status and #status=" do
expect { cbv.status = :wat }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
expect { cbv.status }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
diff --git a/spec/unit/deprecation_spec.rb b/spec/unit/deprecation_spec.rb
index f824cb7c76..2e1f3c39f3 100644
--- a/spec/unit/deprecation_spec.rb
+++ b/spec/unit/deprecation_spec.rb
@@ -95,4 +95,59 @@ describe Chef::Deprecation do
expect { test_instance.deprecated_method(10) }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
end
+ context "When a class has deprecated_attr, _reader and _writer" do
+ before(:context) do
+ class DeprecatedAttrTest
+ extend Chef::Mixin::Deprecation
+ def initialize
+ @a = @r = @w = 1
+ end
+ deprecated_attr :a, "a"
+ deprecated_attr_reader :r, "r"
+ deprecated_attr_writer :w, "w"
+ end
+ end
+
+ it "The deprecated_attr emits warnings" do
+ test = DeprecatedAttrTest.new
+ expect { test.a = 10 }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
+ expect { test.a }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
+ end
+
+ it "The deprecated_attr_writer emits warnings, and does not create a reader" do
+ test = DeprecatedAttrTest.new
+ expect { test.w = 10 }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
+ expect { test.w }.to raise_error(NoMethodError)
+ end
+
+ it "The deprecated_attr_reader emits warnings, and does not create a writer" do
+ test = DeprecatedAttrTest.new
+ expect { test.r = 10 }.to raise_error(NoMethodError)
+ expect { test.r }.to raise_error(Chef::Exceptions::DeprecatedFeatureError)
+ end
+
+ context "With deprecation warnings not throwing exceptions" do
+ before do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
+ end
+
+ it "The deprecated_attr can be written to and read from" do
+ test = DeprecatedAttrTest.new
+ test.a = 10
+ expect(test.a).to eq 10
+ end
+
+ it "The deprecated_attr_reader can be read from" do
+ test = DeprecatedAttrTest.new
+ expect(test.r).to eq 1
+ end
+
+ it "The deprecated_attr_writer can be written to" do
+ test = DeprecatedAttrTest.new
+ test.w = 10
+ expect(test.instance_eval { @w }).to eq 10
+ end
+ end
+ end
+
end
diff --git a/spec/unit/exceptions_spec.rb b/spec/unit/exceptions_spec.rb
index d35ecc8ec8..fd90aeab71 100644
--- a/spec/unit/exceptions_spec.rb
+++ b/spec/unit/exceptions_spec.rb
@@ -113,7 +113,7 @@ describe Chef::Exceptions do
context "initialized with 1 error and nil" do
let(:e) { Chef::Exceptions::RunFailedWrappingError.new(RuntimeError.new("foo"), nil) }
let(:num_errors) { 1 }
- let(:backtrace) { ["1) RuntimeError - foo", ""] }
+ let(:backtrace) { ["1) RuntimeError - foo"] }
include_examples "RunFailedWrappingError expectations"
end
@@ -121,7 +121,7 @@ describe Chef::Exceptions do
context "initialized with 2 errors" do
let(:e) { Chef::Exceptions::RunFailedWrappingError.new(RuntimeError.new("foo"), RuntimeError.new("bar")) }
let(:num_errors) { 2 }
- let(:backtrace) { ["1) RuntimeError - foo", "", "2) RuntimeError - bar", ""] }
+ let(:backtrace) { ["1) RuntimeError - foo", "", "2) RuntimeError - bar"] }
include_examples "RunFailedWrappingError expectations"
end
diff --git a/spec/unit/formatters/doc_spec.rb b/spec/unit/formatters/doc_spec.rb
new file mode 100644
index 0000000000..d018207f49
--- /dev/null
+++ b/spec/unit/formatters/doc_spec.rb
@@ -0,0 +1,46 @@
+#
+# Author:: Daniel DeLeo (<dan@chef.io>)
+#
+# Copyright:: Copyright (c) 2015 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+
+describe Chef::Formatters::Base do
+
+ let(:out) { StringIO.new }
+ let(:err) { StringIO.new }
+
+ subject(:formatter) { Chef::Formatters::Doc.new(out, err) }
+
+ it "prints a policyfile's name and revision ID" do
+ minimal_policyfile = {
+ "revision_id"=> "613f803bdd035d574df7fa6da525b38df45a74ca82b38b79655efed8a189e073",
+ "name"=> "jenkins",
+ "run_list"=> [
+ "recipe[apt::default]",
+ "recipe[java::default]",
+ "recipe[jenkins::master]",
+ "recipe[policyfile_demo::default]"
+ ],
+ "cookbook_locks"=> { }
+ }
+
+ formatter.policyfile_loaded(minimal_policyfile)
+ expect(out.string).to include("Using policy 'jenkins' at revision '613f803bdd035d574df7fa6da525b38df45a74ca82b38b79655efed8a189e073'")
+ end
+
+end
diff --git a/spec/unit/knife/core/subcommand_loader_spec.rb b/spec/unit/knife/core/subcommand_loader_spec.rb
index 76ebf154db..219a1f2906 100644
--- a/spec/unit/knife/core/subcommand_loader_spec.rb
+++ b/spec/unit/knife/core/subcommand_loader_spec.rb
@@ -22,14 +22,14 @@ describe Chef::Knife::SubcommandLoader do
let(:loader) { Chef::Knife::SubcommandLoader.new(File.join(CHEF_SPEC_DATA, 'knife-site-subcommands')) }
let(:home) { File.join(CHEF_SPEC_DATA, 'knife-home') }
let(:plugin_dir) { File.join(home, '.chef', 'plugins', 'knife') }
-
+
before do
allow(ChefConfig).to receive(:windows?) { false }
- Chef::Util::PathHelper.class_variable_set(:@@home_dir, home)
+ Chef::Util::PathHelper.class_variable_set(:@@home_dir, home)
end
after do
- Chef::Util::PathHelper.class_variable_set(:@@home_dir, nil)
+ Chef::Util::PathHelper.class_variable_set(:@@home_dir, nil)
end
it "builds a list of the core subcommand file require paths" do
@@ -106,6 +106,18 @@ describe Chef::Knife::SubcommandLoader do
# Chef 12.0.0.rc.0 gem also:
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.rc.0/lib/chef/knife/thing.rb",
+ # Test that we ignore the platform suffix when checking for different
+ # gem versions.
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-x86-mingw32/lib/chef/knife/valid.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-i386-mingw64/lib/chef/knife/valid-too.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-mswin32/lib/chef/knife/also-valid.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-universal-mingw32/lib/chef/knife/universal-is-valid.rb",
+ # ...but don't ignore the .rc / .dev parts in the case when we have
+ # platform suffixes
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.rc.0-x86-mingw32/lib/chef/knife/invalid.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.dev-mswin32/lib/chef/knife/invalid-too.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}.dev.0-x86-mingw64/lib/chef/knife/still-invalid.rb",
+
# This command is "extra" compared to what's in the embedded/apps/chef install:
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-1.0.0/lib/chef/knife/data_bag_secret_options.rb",
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb",
@@ -133,6 +145,10 @@ describe Chef::Knife::SubcommandLoader do
"/opt/chefdk/embedded/apps/chef/lib/chef/knife/bootstrap.rb",
"/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_bulk_delete.rb",
"/opt/chefdk/embedded/apps/chef/lib/chef/knife/client_create.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-x86-mingw32/lib/chef/knife/valid.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-i386-mingw64/lib/chef/knife/valid-too.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-mswin32/lib/chef/knife/also-valid.rb",
+ "/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-#{Chef::VERSION}-universal-mingw32/lib/chef/knife/universal-is-valid.rb",
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-vault-2.2.4/lib/chef/knife/decrypt.rb",
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/knife-spork-1.4.1/lib/chef/knife/spork-bump.rb",
"/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-foo-#{Chef::VERSION}/lib/chef/knife/chef-foo.rb",
diff --git a/spec/unit/knife/core/ui_spec.rb b/spec/unit/knife/core/ui_spec.rb
index 4f48d4ff0d..ab420518a3 100644
--- a/spec/unit/knife/core/ui_spec.rb
+++ b/spec/unit/knife/core/ui_spec.rb
@@ -368,6 +368,20 @@ EOM
@ui.config[:attribute] = "keys.keys"
expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { "keys.keys" => "values" } })
end
+
+ it "should return the name attribute" do
+ allow_any_instance_of(Chef::Node).to receive(:name).and_return("chef.localdomain")
+ input = Chef::Node.new
+ @ui.config[:attribute] = "name"
+ expect(@ui.format_for_display(input)).to eq( {"chef.localdomain"=>{"name"=>"chef.localdomain"} })
+ end
+
+ it "returns nil when given an attribute path that isn't a name or attribute" do
+ input = { "keys" => {"keys" => "values"}, "hi" => "ho", "id" => "sample-data-bag-item" }
+ non_existing_path = "nope.nada.nothingtoseehere"
+ @ui.config[:attribute] = non_existing_path
+ expect(@ui.format_for_display(input)).to eq({ "sample-data-bag-item" => { non_existing_path => nil } })
+ end
end
describe "with --run-list passed" do
diff --git a/spec/unit/mixin/command_spec.rb b/spec/unit/mixin/command_spec.rb
index e198e3addd..050b261256 100644
--- a/spec/unit/mixin/command_spec.rb
+++ b/spec/unit/mixin/command_spec.rb
@@ -22,7 +22,7 @@ describe Chef::Mixin::Command, :volatile do
if windows?
- pending("TODO MOVE: this is a platform specific integration test.")
+ skip("TODO MOVE: this is a platform specific integration test.")
else
@@ -61,7 +61,6 @@ describe Chef::Mixin::Command, :volatile do
it "returns immediately after the first child process exits" do
expect {Timeout.timeout(10) do
- pid, stdin,stdout,stderr = nil,nil,nil,nil
evil_forker="exit if fork; 10.times { sleep 1}"
popen4("ruby -e '#{evil_forker}'") do |pid,stdin,stdout,stderr|
end
diff --git a/spec/unit/mixin/powershell_out_spec.rb b/spec/unit/mixin/powershell_out_spec.rb
new file mode 100644
index 0000000000..0fede582fa
--- /dev/null
+++ b/spec/unit/mixin/powershell_out_spec.rb
@@ -0,0 +1,70 @@
+#
+# Copyright:: Copyright (c) 2015 Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'spec_helper'
+require 'chef/mixin/powershell_out'
+
+describe Chef::Mixin::PowershellOut do
+ let(:shell_out_class) { Class.new { include Chef::Mixin::PowershellOut } }
+ subject(:object) { shell_out_class.new }
+ let(:architecture) { "something" }
+ let(:flags) {
+ "-NoLogo -NonInteractive -NoProfile -ExecutionPolicy Unrestricted -InputFormat None"
+ }
+
+ describe "#powershell_out" do
+ it "runs a command and returns the shell_out object" do
+ ret = double("Mixlib::ShellOut")
+ expect(object).to receive(:shell_out).with(
+ "powershell.exe #{flags} -Command \"Get-Process\"",
+ {}
+ ).and_return(ret)
+ expect(object.powershell_out("Get-Process")).to eql(ret)
+ end
+
+ it "passes options" do
+ ret = double("Mixlib::ShellOut")
+ expect(object).to receive(:shell_out).with(
+ "powershell.exe #{flags} -Command \"Get-Process\"",
+ timeout: 600
+ ).and_return(ret)
+ expect(object.powershell_out("Get-Process", timeout: 600)).to eql(ret)
+ end
+ end
+
+ describe "#powershell_out!" do
+ it "runs a command and returns the shell_out object" do
+ mixlib_shellout = double("Mixlib::ShellOut")
+ expect(object).to receive(:shell_out).with(
+ "powershell.exe #{flags} -Command \"Get-Process\"",
+ {}
+ ).and_return(mixlib_shellout)
+ expect(mixlib_shellout).to receive(:error!)
+ expect(object.powershell_out!("Get-Process")).to eql(mixlib_shellout)
+ end
+
+ it "passes options" do
+ mixlib_shellout = double("Mixlib::ShellOut")
+ expect(object).to receive(:shell_out).with(
+ "powershell.exe #{flags} -Command \"Get-Process\"",
+ timeout: 600
+ ).and_return(mixlib_shellout)
+ expect(mixlib_shellout).to receive(:error!)
+ expect(object.powershell_out!("Get-Process", timeout: 600)).to eql(mixlib_shellout)
+ end
+ end
+end
diff --git a/spec/unit/provider/directory_spec.rb b/spec/unit/provider/directory_spec.rb
index 6489f2ca50..38d6db8320 100644
--- a/spec/unit/provider/directory_spec.rb
+++ b/spec/unit/provider/directory_spec.rb
@@ -16,173 +16,237 @@
# limitations under the License.
#
-require 'ostruct'
-
require 'spec_helper'
require 'tmpdir'
describe Chef::Provider::Directory do
- before(:each) do
- @new_resource = Chef::Resource::Directory.new(Dir.tmpdir)
- if !windows?
- @new_resource.owner(500)
- @new_resource.group(500)
- @new_resource.mode(0644)
+ let(:tmp_dir) { Dir.mktmpdir }
+ let(:new_resource) { Chef::Resource::Directory.new(tmp_dir) }
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:directory) { Chef::Provider::Directory.new(new_resource, run_context) }
+
+ describe "#load_current_resource" do
+ describe "scanning file security metadata"
+ describe "on unix", unix_only: true do
+ describe "when the directory exists" do
+ let(:dir_stat) { File::Stat.new(tmp_dir) }
+ let(:expected_uid) { dir_stat.uid }
+ let(:expected_gid) { dir_stat.gid }
+ let(:expected_mode) { "0%o" % ( dir_stat.mode & 007777 ) }
+ let(:expected_pwnam) { Etc.getpwuid(expected_uid).name }
+ let(:expected_grnam) { Etc.getgrgid(expected_gid).name }
+
+ it "describes the access mode as a String of octal integers" do
+ directory.load_current_resource
+ expect(directory.current_resource.mode).to eq(expected_mode)
+ end
+
+ it "when the new_resource.owner is numeric, describes the owner as a numeric uid" do
+ new_resource.owner(500)
+ directory.load_current_resource
+ expect(directory.current_resource.owner).to eql(expected_uid)
+ end
+
+ it "when the new_resource.group is numeric, describes the group as a numeric gid" do
+ new_resource.group(500)
+ directory.load_current_resource
+ expect(directory.current_resource.group).to eql(expected_gid)
+ end
+
+ it "when the new_resource.owner is a string, describes the owner as a string" do
+ new_resource.owner("foo")
+ directory.load_current_resource
+ expect(directory.current_resource.owner).to eql(expected_pwnam)
+ end
+
+ it "when the new_resource.group is a string, describes the group as a string" do
+ new_resource.group("bar")
+ directory.load_current_resource
+ expect(directory.current_resource.group).to eql(expected_grnam)
+ end
+ end
end
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @directory = Chef::Provider::Directory.new(@new_resource, @run_context)
- end
+ describe "on windows", windows_only: true do
+ describe "when the directory exists" do
+ it "the mode is always nil" do
+ directory.load_current_resource
+ expect(directory.current_resource.mode).to be nil
+ end
+
+ it "the owner is always nil" do
+ directory.load_current_resource
+ expect(directory.current_resource.owner).to be nil
+ end
+
+ it "the group is always nil" do
+ directory.load_current_resource
+ expect(directory.current_resource.group).to be nil
+ end
+
+ it "rights are always nil (incorrectly)" do
+ directory.load_current_resource
+ expect(directory.current_resource.rights).to be nil
+ end
+
+ it "inherits is always nil (incorrectly)" do
+ directory.load_current_resource
+ expect(directory.current_resource.inherits).to be nil
+ end
+ end
+ end
+ describe "when the directory does not exist" do
+ before do
+ FileUtils.rmdir tmp_dir
+ end
- describe "scanning file security metadata on windows" do
- before do
+ it "sets the mode, group and owner to nil" do
+ directory.load_current_resource
+ expect(directory.current_resource.mode).to eq(nil)
+ expect(directory.current_resource.group).to eq(nil)
+ expect(directory.current_resource.owner).to eq(nil)
+ end
end
- it "describes the directory's access rights" do
- skip
- end
end
- describe "scanning file security metadata on unix" do
- before do
- allow(ChefConfig).to receive(:windows?).and_return(false)
- end
- let(:mock_stat) do
- cstats = double("stats")
- allow(cstats).to receive(:uid).and_return(500)
- allow(cstats).to receive(:gid).and_return(500)
- allow(cstats).to receive(:mode).and_return(0755)
- cstats
- end
+ describe "#define_resource_requirements" do
+ describe "on unix", unix_only: true do
+ it "raises an exception if the user does not exist" do
+ new_resource.owner("arglebargle_iv")
+ expect(Etc).to receive(:getpwnam).with("arglebargle_iv").and_raise(ArgumentError)
+ directory.action = :create
+ directory.load_current_resource
+ expect(directory.access_controls).to receive(:define_resource_requirements).and_call_original
+ directory.define_resource_requirements
+ expect { directory.process_resource_requirements }.to raise_error(ArgumentError)
+ end
- it "describes the access mode as a String of octal integers" do
- allow(File).to receive(:exists?).and_return(true)
- expect(File).to receive(:stat).and_return(mock_stat)
- @directory.load_current_resource
- expect(@directory.current_resource.mode).to eq("0755")
+ it "raises an exception if the group does not exist" do
+ new_resource.group("arglebargle_iv")
+ expect(Etc).to receive(:getgrnam).with("arglebargle_iv").and_raise(ArgumentError)
+ directory.action = :create
+ directory.load_current_resource
+ expect(directory.access_controls).to receive(:define_resource_requirements).and_call_original
+ directory.define_resource_requirements
+ expect { directory.process_resource_requirements }.to raise_error(ArgumentError)
+ end
end
+ end
- context "when user and group are specified with UID/GID" do
- it "describes the current owner and group as UID and GID" do
- allow(File).to receive(:exists?).and_return(true)
- expect(File).to receive(:stat).and_return(mock_stat)
- @directory.load_current_resource
- expect(@directory.current_resource.path).to eql(@new_resource.path)
- expect(@directory.current_resource.owner).to eql(500)
- expect(@directory.current_resource.group).to eql(500)
+ describe "#run_action(:create)" do
+ describe "when the directory exists" do
+ it "does not create the directory" do
+ expect(Dir).not_to receive(:mkdir).with(new_resource.path)
+ directory.run_action(:create)
+ end
+
+ it "should not set the resource as updated" do
+ directory.run_action(:create)
+ expect(new_resource).not_to be_updated
end
end
- context "when user/group are specified with user/group names" do
+ describe "when the directory does not exist" do
+ before do
+ FileUtils.rmdir tmp_dir
+ end
+
+ it "creates the directory" do
+ directory.run_action(:create)
+ expect(File.exist?(tmp_dir)).to be true
+ end
+
+ it "sets the new resource as updated" do
+ directory.run_action(:create)
+ expect(new_resource).to be_updated
+ end
end
- end
- # Unix only for now. While file security attribute reporting for windows is
- # disabled, unix and windows differ in the number of exists? calls that are
- # made by the provider.
- it "should create a new directory on create, setting updated to true", :unix_only do
- @new_resource.path "/tmp/foo"
+ describe "when the parent directory does not exist" do
+ before do
+ new_resource.path "#{tmp_dir}/foobar"
+ FileUtils.rmdir tmp_dir
+ end
- expect(File).to receive(:exists?).at_least(:once).and_return(false)
- expect(File).to receive(:directory?).with("/tmp").and_return(true)
- expect(Dir).to receive(:mkdir).with(@new_resource.path).once.and_return(true)
+ it "raises an exception when recursive is false" do
+ new_resource.recursive false
+ expect { directory.run_action(:create) }.to raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ end
- expect(@directory).to receive(:do_acl_changes)
- allow(@directory).to receive(:do_selinux)
- @directory.run_action(:create)
- expect(@directory.new_resource).to be_updated
- end
+ it "creates the directories when recursive is true" do
+ new_resource.recursive true
+ directory.run_action(:create)
+ expect(new_resource).to be_updated
+ expect(File.exist?("#{tmp_dir}/foobar")).to be true
+ end
- it "should raise an exception if the parent directory does not exist and recursive is false" do
- @new_resource.path "/tmp/some/dir"
- @new_resource.recursive false
- expect { @directory.run_action(:create) }.to raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- end
+ it "raises an exception when the parent directory is a file and recursive is true" do
+ FileUtils.touch tmp_dir
+ new_resource.recursive true
+ expect { directory.run_action(:create) }.to raise_error
+ end
- # Unix only for now. While file security attribute reporting for windows is
- # disabled, unix and windows differ in the number of exists? calls that are
- # made by the provider.
- it "should create a new directory when parent directory does not exist if recursive is true and permissions are correct", :unix_only do
- @new_resource.path "/path/to/dir"
- @new_resource.recursive true
- expect(File).to receive(:exists?).with(@new_resource.path).ordered.and_return(false)
-
- expect(File).to receive(:exists?).with('/path/to').ordered.and_return(false)
- expect(File).to receive(:exists?).with('/path').ordered.and_return(true)
- expect(Chef::FileAccessControl).to receive(:writable?).with('/path').ordered.and_return(true)
- expect(File).to receive(:exists?).with(@new_resource.path).ordered.and_return(false)
-
- expect(FileUtils).to receive(:mkdir_p).with(@new_resource.path).and_return(true)
- expect(@directory).to receive(:do_acl_changes)
- allow(@directory).to receive(:do_selinux)
- @directory.run_action(:create)
- expect(@new_resource).to be_updated
+ it "raises the right exception when the parent directory is a file and recursive is true" do
+ pending "this seems to return the wrong error" # FIXME
+ FileUtils.touch tmp_dir
+ new_resource.recursive true
+ expect { directory.run_action(:create) }.to raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ end
+ end
end
+ describe "#run_action(:create)" do
+ describe "when the directory exists" do
+ it "deletes the directory" do
+ directory.run_action(:delete)
+ expect(File.exist?(tmp_dir)).to be false
+ end
- it "should raise an error when creating a directory when parent directory is a file" do
- expect(File).to receive(:directory?).and_return(false)
- expect(Dir).not_to receive(:mkdir).with(@new_resource.path)
- expect { @directory.run_action(:create) }.to raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- expect(@directory.new_resource).not_to be_updated
- end
+ it "sets the new resource as updated" do
+ directory.run_action(:delete)
+ expect(new_resource).to be_updated
+ end
+ end
- # Unix only for now. While file security attribute reporting for windows is
- # disabled, unix and windows differ in the number of exists? calls that are
- # made by the provider.
- it "should not create the directory if it already exists", :unix_only do
- stub_file_cstats
- @new_resource.path "/tmp/foo"
- expect(File).to receive(:directory?).at_least(:once).and_return(true)
- expect(Chef::FileAccessControl).to receive(:writable?).with("/tmp").and_return(true)
- expect(File).to receive(:exists?).at_least(:once).and_return(true)
- expect(Dir).not_to receive(:mkdir).with(@new_resource.path)
- expect(@directory).to receive(:do_acl_changes)
- @directory.run_action(:create)
- end
+ describe "when the directory does not exist" do
+ before do
+ FileUtils.rmdir tmp_dir
+ end
- it "should delete the directory if it exists, and is writable with action_delete" do
- expect(File).to receive(:directory?).and_return(true)
- expect(Chef::FileAccessControl).to receive(:writable?).once.and_return(true)
- expect(Dir).to receive(:delete).with(@new_resource.path).once.and_return(true)
- @directory.run_action(:delete)
- end
+ it "does not delete the directory" do
+ expect(Dir).not_to receive(:delete).with(new_resource.path)
+ directory.run_action(:delete)
+ end
- it "should raise an exception if it cannot delete the directory due to bad permissions" do
- allow(File).to receive(:exists?).and_return(true)
- allow(Chef::FileAccessControl).to receive(:writable?).and_return(false)
- expect { @directory.run_action(:delete) }.to raise_error(RuntimeError)
- end
+ it "sets the new resource as updated" do
+ directory.run_action(:delete)
+ expect(new_resource).not_to be_updated
+ end
+ end
- it "should take no action when deleting a target directory that does not exist" do
- @new_resource.path "/an/invalid/path"
- allow(File).to receive(:exists?).and_return(false)
- expect(Dir).not_to receive(:delete).with(@new_resource.path)
- @directory.run_action(:delete)
- expect(@directory.new_resource).not_to be_updated
- end
+ describe "when the directory is not writable" do
+ before do
+ allow(Chef::FileAccessControl).to receive(:writable?).and_return(false)
+ end
- it "should raise an exception when deleting a directory when target directory is a file" do
- stub_file_cstats
- @new_resource.path "/an/invalid/path"
- allow(File).to receive(:exists?).and_return(true)
- expect(File).to receive(:directory?).and_return(false)
- expect(Dir).not_to receive(:delete).with(@new_resource.path)
- expect { @directory.run_action(:delete) }.to raise_error(RuntimeError)
- expect(@directory.new_resource).not_to be_updated
- end
+ it "cannot delete it and raises an exception" do
+ expect { directory.run_action(:delete) }.to raise_error(RuntimeError)
+ end
+ end
+
+ describe "when the target directory is a file" do
+ before do
+ FileUtils.rmdir tmp_dir
+ FileUtils.touch tmp_dir
+ end
- def stub_file_cstats
- cstats = double("stats")
- allow(cstats).to receive(:uid).and_return(500)
- allow(cstats).to receive(:gid).and_return(500)
- allow(cstats).to receive(:mode).and_return(0755)
- # File.stat is called in:
- # - Chef::Provider::File.load_current_resource_attrs
- # - Chef::ScanAccessControl via Chef::Provider::File.setup_acl
- allow(File).to receive(:stat).and_return(cstats)
+ it "cannot delete it and raises an exception" do
+ expect { directory.run_action(:delete) }.to raise_error(RuntimeError)
+ end
+ end
end
end
diff --git a/spec/unit/provider/ifconfig/debian_spec.rb b/spec/unit/provider/ifconfig/debian_spec.rb
index 351e734040..0c02ae9cd4 100644
--- a/spec/unit/provider/ifconfig/debian_spec.rb
+++ b/spec/unit/provider/ifconfig/debian_spec.rb
@@ -144,11 +144,6 @@ EOF
expect(IO.read(tempfile.path)).to eq(expected_string)
end
- it "should not mark the resource as updated" do
- provider.run_action(:add)
- pending "superclass ifconfig provider is not idempotent"
- expect(new_resource.updated_by_last_action?).to be_falsey
- end
end
context "when the /etc/network/interfaces file does not have the source line" do
@@ -280,11 +275,6 @@ another line
expect(IO.read(tempfile.path)).to eq(expected_string)
end
- it "should not mark the resource as updated" do
- provider.run_action(:add)
- pending "superclass ifconfig provider is not idempotent"
- expect(new_resource.updated_by_last_action?).to be_falsey
- end
end
context "when the /etc/network/interfaces file does not have the source line" do
diff --git a/spec/unit/provider/package/openbsd_spec.rb b/spec/unit/provider/package/openbsd_spec.rb
index b0cdb9969d..abe94474a4 100644
--- a/spec/unit/provider/package/openbsd_spec.rb
+++ b/spec/unit/provider/package/openbsd_spec.rb
@@ -50,18 +50,6 @@ describe Chef::Provider::Package::Openbsd do
context 'when there is a single candidate' do
- context 'when installing from source' do
- it 'should run the installation command' do
- pending('Installing from source is not supported yet')
- # This is a consequence of load_current_resource being called before define_resource_requirements
- # It can be deleted once an implementation is provided
- allow(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
- instance_double('shellout', :stdout => "#{name}-#{version}\n"))
- new_resource.source('/some/path/on/disk.tgz')
- provider.run_action(:install)
- end
- end
-
context 'when source is not provided' do
it 'should run the installation command' do
expect(provider).to receive(:shell_out!).with("pkg_info -I \"#{name}\"", anything()).and_return(
@@ -106,15 +94,6 @@ describe Chef::Provider::Package::Openbsd do
end
end
- context 'if a version is specified' do
- it 'runs the installation command' do
- pending('Specifying both a version and flavor is not supported')
- new_resource.version(version)
- allow(provider).to receive(:shell_out!).with(/pkg_info -e/, anything()).and_return(instance_double('shellout', :stdout => ''))
- allow(provider).to receive(:candidate_version).and_return("#{package_name}-#{version}-#{flavor}")
- provider.run_action(:install)
- end
- end
end
context 'if a version is specified' do
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index 380572499c..3ccc69652f 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -222,8 +222,6 @@ describe Chef::Provider::Package::Rubygems::AlternateGemEnvironment do
end
it "uses the cached result for gem paths when available" do
- gem_env_output = ['/path/to/gems', '/another/path/to/gems'].join(File::PATH_SEPARATOR)
- shell_out_result = OpenStruct.new(:stdout => gem_env_output)
expect(@gem_env).not_to receive(:shell_out!)
expected = ['/path/to/gems', '/another/path/to/gems']
Chef::Provider::Package::Rubygems::AlternateGemEnvironment.gempath_cache['/usr/weird/bin/gem']= expected
@@ -261,7 +259,7 @@ describe Chef::Provider::Package::Rubygems::AlternateGemEnvironment do
else
`which gem`.strip
end
- pending("cant find your gem executable") if path_to_gem.empty?
+ skip("cant find your gem executable") if path_to_gem.empty?
gem_env = Chef::Provider::Package::Rubygems::AlternateGemEnvironment.new(path_to_gem)
expected = ['rspec-core', Gem::Version.new(RSpec::Core::Version::STRING)]
actual = gem_env.installed_versions(Gem::Dependency.new('rspec-core', nil)).map { |s| [s.name, s.version] }
diff --git a/spec/unit/provider/powershell_spec.rb b/spec/unit/provider/powershell_spec.rb
index 60dbcf80b0..855c18af9b 100644
--- a/spec/unit/provider/powershell_spec.rb
+++ b/spec/unit/provider/powershell_spec.rb
@@ -19,20 +19,62 @@
require 'spec_helper'
describe Chef::Provider::PowershellScript, "action_run" do
- before(:each) do
- @node = Chef::Node.new
+ let(:powershell_version) { nil }
+ let(:node) {
+ node = Chef::Node.new
+ node.default["kernel"] = Hash.new
+ node.default["kernel"][:machine] = :x86_64.to_s
+ if ! powershell_version.nil?
+ node.default[:languages] = { :powershell => { :version => powershell_version } }
+ end
+ node
+ }
- @node.default["kernel"] = Hash.new
- @node.default["kernel"][:machine] = :x86_64.to_s
+ let(:provider) {
+ empty_events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, empty_events)
+ new_resource = Chef::Resource::PowershellScript.new('run some powershell code', run_context)
+ Chef::Provider::PowershellScript.new(new_resource, run_context)
+ }
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = Chef::Resource::PowershellScript.new('run some powershell code', @run_context)
+ context 'when setting interpreter flags' do
+ it "should set the -File flag as the last flag" do
+ expect(provider.flags.split(' ').pop).to eq("-File")
+ end
- @provider = Chef::Provider::PowershellScript.new(@new_resource, @run_context)
- end
+ let(:execution_policy_flag) do
+ execution_policy_index = 0
+ provider_flags = provider.flags.split(' ')
+ execution_policy_specified = false
- it "should set the -File flag as the last flag" do
- expect(@provider.flags.split(' ').pop).to eq("-File")
- end
+ provider_flags.find do | value |
+ execution_policy_index += 1
+ execution_policy_specified = value.downcase == '-ExecutionPolicy'.downcase
+ end
+
+ execution_policy = execution_policy_specified ? provider_flags[execution_policy_index] : nil
+ end
+ context 'when running with an unspecified PowerShell version' do
+ let(:powershell_version) { nil }
+ it "should set the -ExecutionPolicy flag to 'Unrestricted' by default" do
+ expect(execution_policy_flag.downcase).to eq('unrestricted'.downcase)
+ end
+ end
+
+ { '2.0' => 'Unrestricted',
+ '2.5' => 'Unrestricted',
+ '3.0' => 'Bypass',
+ '3.6' => 'Bypass',
+ '4.0' => 'Bypass',
+ '5.0' => 'Bypass' }.each do | version_policy |
+ let(:powershell_version) { version_policy[0].to_f }
+ context "when running PowerShell version #{version_policy[0]}" do
+ let(:powershell_version) { version_policy[0].to_f }
+ it "should set the -ExecutionPolicy flag to '#{version_policy[1]}'" do
+ expect(execution_policy_flag.downcase).to eq(version_policy[1].downcase)
+ end
+ end
+ end
+ end
end
diff --git a/spec/unit/provider/remote_directory_spec.rb b/spec/unit/provider/remote_directory_spec.rb
index 4434714ebc..99e2fe285c 100644
--- a/spec/unit/provider/remote_directory_spec.rb
+++ b/spec/unit/provider/remote_directory_spec.rb
@@ -194,8 +194,8 @@ describe Chef::Provider::RemoteDirectory do
expect(::File.exist?(symlinked_dir_path)).to be_falsey
expect(::File.exist?(tmp_dir)).to be_truthy
- rescue Chef::Exceptions::Win32APIError => e
- pending "This must be run as an Administrator to create symlinks"
+ rescue Chef::Exceptions::Win32APIError
+ skip "This must be run as an Administrator to create symlinks"
end
end
end
diff --git a/spec/unit/provider/service/freebsd_service_spec.rb b/spec/unit/provider/service/freebsd_service_spec.rb
index 5a55425d87..cfc28c94d5 100644
--- a/spec/unit/provider/service/freebsd_service_spec.rb
+++ b/spec/unit/provider/service/freebsd_service_spec.rb
@@ -189,18 +189,6 @@ PS_SAMPLE
expect(provider.status_load_success).to be_nil
end
- context "when ps command is nil" do
- before do
- node.automatic_attrs[:command] = {:ps => nil}
- end
-
- it "should set running to nil" do
- pending "superclass raises no conversion of nil to string which seems broken"
- provider.determine_current_status!
- expect(current_resource.running).to be_nil
- end
- end
-
context "when ps is empty string" do
before do
node.automatic_attrs[:command] = {:ps => ""}
diff --git a/spec/unit/provider/user_spec.rb b/spec/unit/provider/user_spec.rb
index 381168647b..2345ce18fb 100644
--- a/spec/unit/provider/user_spec.rb
+++ b/spec/unit/provider/user_spec.rb
@@ -143,8 +143,8 @@ describe Chef::Provider::User do
begin
require 'rubygems'
require 'shadow'
- rescue LoadError => e
- pending "ruby-shadow gem not installed for dynamic load test"
+ rescue LoadError
+ skip "ruby-shadow gem not installed for dynamic load test"
true
else
false
@@ -161,7 +161,7 @@ describe Chef::Provider::User do
unless shadow_lib_unavail?
context "and we have the ruby-shadow gem" do
- pending "and we are not root (rerun this again as root)", :requires_unprivileged_user => true
+ skip "and we are not root (rerun this again as root)", :requires_unprivileged_user => true
context "and we are root", :requires_root => true do
it "should pass assertions when ruby-shadow can be loaded" do
diff --git a/spec/unit/resource/template_spec.rb b/spec/unit/resource/template_spec.rb
index df5ca94b8a..2fd951b72d 100644
--- a/spec/unit/resource/template_spec.rb
+++ b/spec/unit/resource/template_spec.rb
@@ -98,7 +98,7 @@ describe Chef::Resource::Template do
context "on windows", :windows_only do
# according to Chef::Resource::File, windows state attributes are rights + deny_rights
- pending "it describes its state"
+ skip "it describes its state"
end
it "returns the file path as its identity" do
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 0479778f55..3bfd63f5ab 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -35,6 +35,18 @@ describe Chef::Resource do
@resource = Chef::Resource.new("funk", @run_context)
end
+ it "should mixin shell_out" do
+ expect(@resource.respond_to?(:shell_out)).to be true
+ end
+
+ it "should mixin shell_out!" do
+ expect(@resource.respond_to?(:shell_out!)).to be true
+ end
+
+ it "should mixin shell_out_with_systems_locale" do
+ expect(@resource.respond_to?(:shell_out_with_systems_locale)).to be true
+ end
+
describe "when inherited" do
it "adds an entry to a list of subclasses" do