summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2020-04-02 09:28:22 -0700
committerGitHub <noreply@github.com>2020-04-02 09:28:22 -0700
commit78175f8d4b195b819cf1a6dee26767c870f9f20b (patch)
tree3b7584a5bd6417e5b9eedd4b37fd84fe96a360b3 /spec
parent3ec89bc7d523bf623505d6f55fb553fa5ef2a4d7 (diff)
parentf24948d75a8f0c08d4705e7bc194bfd4b2a3a7d3 (diff)
downloadchef-78175f8d4b195b819cf1a6dee26767c870f9f20b.tar.gz
Merge pull request #9562 from chef/lcg/after-resource
Add after_resource to pair with current_resource
Diffstat (limited to 'spec')
-rw-r--r--spec/integration/recipes/resource_load_spec.rb141
-rw-r--r--spec/unit/data_collector_spec.rb57
-rw-r--r--spec/unit/resource/chocolatey_source_spec.rb5
3 files changed, 173 insertions, 30 deletions
diff --git a/spec/integration/recipes/resource_load_spec.rb b/spec/integration/recipes/resource_load_spec.rb
index 3ca71c3a03..52a108a766 100644
--- a/spec/integration/recipes/resource_load_spec.rb
+++ b/spec/integration/recipes/resource_load_spec.rb
@@ -65,17 +65,17 @@ describe "Resource.load_current_value" do
end
it "current_resource is passed name but not x" do
- expect(resource.current_value.x).to eq "loaded 2 (name=blah)"
+ expect(resource.current_value.x).to eq "loaded 3 (name=blah)"
end
it "resource.current_value returns a different resource" do
- expect(resource.current_value.x).to eq "loaded 2 (name=blah)"
+ expect(resource.current_value.x).to eq "loaded 3 (name=blah)"
expect(resource.x).to eq "desired"
end
it "resource.current_value constructs the resource anew each time" do
- expect(resource.current_value.x).to eq "loaded 2 (name=blah)"
expect(resource.current_value.x).to eq "loaded 3 (name=blah)"
+ expect(resource.current_value.x).to eq "loaded 4 (name=blah)"
end
it "the provider accesses the current value of x" do
@@ -96,7 +96,7 @@ describe "Resource.load_current_value" do
end
it "i, name and d are passed to load_current_value, but not x" do
- expect(resource.current_value.x).to eq "loaded 2 (d=desired_d, i=desired_i, name=blah)"
+ expect(resource.current_value.x).to eq "loaded 3 (d=desired_d, i=desired_i, name=blah)"
end
end
@@ -114,7 +114,7 @@ describe "Resource.load_current_value" do
end
it "i, name and d are passed to load_current_value, but not x" do
- expect(resource.current_value.x).to eq "loaded 2 (d=desired_d, i=desired_i, name=blah)"
+ expect(resource.current_value.x).to eq "loaded 3 (d=desired_d, i=desired_i, name=blah)"
end
end
end
@@ -146,7 +146,7 @@ describe "Resource.load_current_value" do
context "and a child resource class with no load_current_value" do
it "the parent load_current_value is used" do
- expect(subresource.current_value.x).to eq "loaded 2 (name=blah)"
+ expect(subresource.current_value.x).to eq "loaded 3 (name=blah)"
end
it "load_current_value yields a copy of the child class" do
expect(subresource.current_value).to be_kind_of(subresource_class)
@@ -165,8 +165,8 @@ describe "Resource.load_current_value" do
it "the overridden load_current_value is used" do
current_resource = subresource.current_value
- expect(current_resource.x).to eq "default 3"
- expect(current_resource.y).to eq "loaded_y 2 (name=blah)"
+ expect(current_resource.x).to eq "default 4"
+ expect(current_resource.y).to eq "loaded_y 3 (name=blah)"
end
end
@@ -183,10 +183,131 @@ describe "Resource.load_current_value" do
it "the original load_current_value is called as well as the child one" do
current_resource = subresource.current_value
- expect(current_resource.x).to eq "loaded 3 (name=blah)"
- expect(current_resource.y).to eq "loaded_y 4 (name=blah, x=loaded 3 (name=blah))"
+ expect(current_resource.x).to eq "loaded 5 (name=blah)"
+ expect(current_resource.y).to eq "loaded_y 6 (name=blah, x=loaded 5 (name=blah))"
+ end
+ end
+ end
+end
+
+describe "simple load_current_value tests" do
+ let(:resource_class) do
+ Class.new(Chef::Resource) do
+ attr_writer :index # this is our hacky global state
+ def index; @index ||= 1; end
+
+ property :myindex, Integer
+
+ load_current_value do |new_resource|
+ myindex new_resource.index
+ end
+
+ action :run do
+ new_resource.index += 1
+ end
+ end
+ end
+
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) { resource_class.new("test", run_context) }
+ let(:provider) { new_resource.provider_for_action(:run) }
+
+ it "calling the action on the provider sets the current_resource" do
+ expect(events).to receive(:resource_current_state_loaded).with(new_resource, :run, anything)
+ provider.run_action(:run)
+ expect(provider.current_resource.myindex).to eql(1)
+ end
+
+ it "calling the action on the provider sets the after_resource" do
+ expect(events).to receive(:resource_after_state_loaded).with(new_resource, :run, anything)
+ provider.run_action(:run)
+ expect(provider.after_resource.myindex).to eql(2)
+ end
+end
+
+describe "simple load_current_resource tests" do
+ let(:provider_class) do
+ Class.new(Chef::Provider) do
+ provides :no_load_current_value
+ def load_current_resource
+ @current_resource = new_resource.dup
+ @current_resource.myindex = 1
+ end
+ action :run do
+ end
+ end
+ end
+
+ let(:resource_class) do
+ provider_class # vivify the provider_class
+ Class.new(Chef::Resource) do
+ provides :no_load_current_value
+ property :myindex, Integer
+ end
+ end
+
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) { resource_class.new("test", run_context) }
+ let(:provider) { new_resource.provider_for_action(:run) }
+
+ it "calling the action on the provider sets the current_resource" do
+ expect(events).to receive(:resource_current_state_loaded).with(new_resource, :run, anything)
+ provider.run_action(:run)
+ expect(provider.current_resource.myindex).to eql(1)
+ end
+
+ it "calling the action on the provider sets the after_resource" do
+ expect(events).to receive(:resource_after_state_loaded).with(new_resource, :run, new_resource)
+ provider.run_action(:run)
+ expect(provider.after_resource.myindex).to eql(nil)
+ end
+end
+
+describe "simple load_current_resource and load_after_resource tests" do
+ let(:provider_class) do
+ Class.new(Chef::Provider) do
+ provides :load_after
+ def load_current_resource
+ @current_resource = new_resource.dup
+ @current_resource.myindex = 1
+ end
+
+ def load_after_resource
+ @after_resource = new_resource.dup
+ @after_resource.myindex = 2
end
+ action :run do
+ end
+ end
+ end
+
+ let(:resource_class) do
+ provider_class # autovivify provider class
+ Class.new(Chef::Resource) do
+ provides :load_after
+ property :myindex, Integer
end
end
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:new_resource) { resource_class.new("test", run_context) }
+ let(:provider) { new_resource.provider_for_action(:run) }
+
+ it "calling the action on the provider sets the current_resource" do
+ expect(events).to receive(:resource_current_state_loaded).with(new_resource, :run, anything)
+ provider.run_action(:run)
+ expect(provider.current_resource.myindex).to eql(1)
+ end
+
+ it "calling the action on the provider sets the after_resource" do
+ expect(events).to receive(:resource_after_state_loaded).with(new_resource, :run, anything)
+ provider.run_action(:run)
+ expect(provider.after_resource.myindex).to eql(2)
+ end
end
diff --git a/spec/unit/data_collector_spec.rb b/spec/unit/data_collector_spec.rb
index 3a1eb5b521..bc234d56aa 100644
--- a/spec/unit/data_collector_spec.rb
+++ b/spec/unit/data_collector_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2019-2019, Chef Software Inc.
+# Copyright:: Copyright 2019-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,6 +19,12 @@ require_relative "../spec_helper"
require "chef/data_collector"
require "socket"
+#
+# FIXME FIXME FIXME: What we need to do here is have the ability to construct a real resource collection
+# with some test resources that will correctly be up-to-date/updated/skipped/failed/unprocessed and really
+# converge a client with them (sort of chefspec-like construction of a Chef::Client but with the actions
+# actually running -- another testing requirement similar to the integration testing framework in cheffish as well)
+#
describe Chef::DataCollector do
before(:each) do
Chef::Config[:enable_reporting] = true
@@ -30,9 +36,23 @@ describe Chef::DataCollector do
let(:data_collector) { Chef::DataCollector::Reporter.new(events) }
- let(:new_resource) { Chef::Resource::File.new("/tmp/a-file.txt") }
+ let(:new_resource) do
+ new_resource = Chef::Resource::File.new("/tmp/a-file.txt")
+ new_resource.checksum nil
+ new_resource
+ end
+
+ let(:current_resource) do
+ current_resource = Chef::Resource::File.new("/tmp/a-file.txt")
+ current_resource.checksum "1234123412341234123412341234123412341234123412341234123412341234"
+ current_resource
+ end
- let(:current_resource) { Chef::Resource::File.new("/tmp/a-file.txt") }
+ let(:after_resource) do
+ after_resource = Chef::Resource::File.new("/tmp/a-file.txt")
+ after_resource.checksum "6789678967896789678967896789678967896789678967896789678967896789"
+ after_resource
+ end
let(:events) { Chef::EventDispatch::Dispatcher.new }
@@ -130,10 +150,10 @@ describe Chef::DataCollector do
new_resource.respond_to?(:diff) && %w{updated failed}.include?(status)
end
- def resource_record_for(current_resource, new_resource, action, status, duration)
+ def resource_record_for(new_resource, before_resource, after_resource, action, status, duration)
{
- "after" => new_resource.state_for_resource_reporter,
- "before" => current_resource&.state_for_resource_reporter,
+ "after" => after_resource&.state_for_resource_reporter || {},
+ "before" => before_resource&.state_for_resource_reporter || {},
"cookbook_name" => cookbook_name,
"cookbook_version" => cookbook_version.version,
"delta" => resource_has_diff(new_resource, status) ? new_resource.diff : "",
@@ -634,13 +654,14 @@ describe Chef::DataCollector do
context "when the run contains a file resource that is up-to-date" do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 0 }
- let(:resource_record) { [ resource_record_for(current_resource, new_resource, :create, "up-to-date", "1234") ] }
+ let(:resource_record) { [ resource_record_for(new_resource, current_resource, after_resource, :create, "up-to-date", "1234") ] }
let(:status) { "success" }
before do
events.resource_action_start(new_resource, :create)
events.resource_current_state_loaded(new_resource, :create, current_resource)
events.resource_up_to_date(new_resource, :create)
+ events.resource_after_state_loaded(new_resource, :create, after_resource)
new_resource.instance_variable_set(:@elapsed_time, 1.2345)
events.resource_completed(new_resource)
events.converge_complete
@@ -653,13 +674,14 @@ describe Chef::DataCollector do
context "when the run contains a file resource that is updated" do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 1 }
- let(:resource_record) { [ resource_record_for(current_resource, new_resource, :create, "updated", "1234") ] }
+ let(:resource_record) { [ resource_record_for(new_resource, current_resource, after_resource, :create, "updated", "1234") ] }
let(:status) { "success" }
before do
events.resource_action_start(new_resource, :create)
events.resource_current_state_loaded(new_resource, :create, current_resource)
events.resource_updated(new_resource, :create)
+ events.resource_after_state_loaded(new_resource, :create, after_resource)
new_resource.instance_variable_set(:@elapsed_time, 1.2345)
events.resource_completed(new_resource)
events.converge_complete
@@ -679,7 +701,7 @@ describe Chef::DataCollector do
allow(r).to receive(:cookbook_version).and_return(cookbook_version)
r
end
- let(:resource_record) { [ resource_record_for(implementation_resource, implementation_resource, :create, "updated", "2345"), resource_record_for(current_resource, new_resource, :create, "updated", "1234") ] }
+ let(:resource_record) { [ resource_record_for(implementation_resource, implementation_resource, implementation_resource, :create, "updated", "2345"), resource_record_for(new_resource, current_resource, after_resource, :create, "updated", "1234") ] }
let(:status) { "success" }
before do
@@ -689,10 +711,12 @@ describe Chef::DataCollector do
events.resource_action_start(implementation_resource , :create)
events.resource_current_state_loaded(implementation_resource, :create, implementation_resource)
events.resource_updated(implementation_resource, :create)
+ events.resource_after_state_loaded(implementation_resource, :create, implementation_resource)
implementation_resource.instance_variable_set(:@elapsed_time, 2.3456)
events.resource_completed(implementation_resource)
events.resource_updated(new_resource, :create)
+ events.resource_after_state_loaded(new_resource, :create, after_resource)
new_resource.instance_variable_set(:@elapsed_time, 1.2345)
events.resource_completed(new_resource)
events.converge_complete
@@ -706,7 +730,7 @@ describe Chef::DataCollector do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 0 }
let(:resource_record) do
- rec = resource_record_for(current_resource, new_resource, :create, "skipped", "1234")
+ rec = resource_record_for(new_resource, nil, nil, :create, "skipped", "1234")
rec["conditional"] = "not_if { #code block }" # FIXME: "#code block" is poor, is there some way to fix this?
[ rec ]
end
@@ -715,7 +739,6 @@ describe Chef::DataCollector do
before do
conditional = (new_resource.not_if { true }).first
events.resource_action_start(new_resource, :create)
- events.resource_current_state_loaded(new_resource, :create, current_resource)
events.resource_skipped(new_resource, :create, conditional)
new_resource.instance_variable_set(:@elapsed_time, 1.2345)
events.resource_completed(new_resource)
@@ -730,7 +753,7 @@ describe Chef::DataCollector do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 0 }
let(:resource_record) do
- rec = resource_record_for(current_resource, new_resource, :create, "skipped", "1234")
+ rec = resource_record_for(new_resource, nil, nil, :create, "skipped", "1234")
rec["conditional"] = 'not_if "true"'
[ rec ]
end
@@ -739,7 +762,6 @@ describe Chef::DataCollector do
before do
conditional = (new_resource.not_if "true").first
events.resource_action_start(new_resource, :create)
- events.resource_current_state_loaded(new_resource, :create, current_resource)
events.resource_skipped(new_resource, :create, conditional)
new_resource.instance_variable_set(:@elapsed_time, 1.2345)
events.resource_completed(new_resource)
@@ -756,7 +778,7 @@ describe Chef::DataCollector do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 0 }
let(:resource_record) do
- rec = resource_record_for(current_resource, new_resource, :create, "failed", "1234")
+ rec = resource_record_for(new_resource, current_resource, nil, :create, "failed", "1234")
rec["error_message"] = "imperial to metric conversion error"
[ rec ]
end
@@ -783,7 +805,7 @@ describe Chef::DataCollector do
let(:total_resource_count) { 1 }
let(:updated_resource_count) { 0 }
let(:resource_record) do
- rec = resource_record_for(current_resource, new_resource, :create, "failed", "1234")
+ rec = resource_record_for(new_resource, nil, nil, :create, "failed", "1234")
rec["before"] = {}
rec["error_message"] = "imperial to metric conversion error"
[ rec ]
@@ -818,10 +840,9 @@ describe Chef::DataCollector do
res
end
let(:resource_record) do
- rec1 = resource_record_for(current_resource, new_resource, :create, "failed", "1234")
+ rec1 = resource_record_for(new_resource, current_resource, nil, :create, "failed", "1234")
rec1["error_message"] = "imperial to metric conversion error"
- rec2 = resource_record_for(nil, unprocessed_resource, :nothing, "unprocessed", "")
- rec2["before"] = {}
+ rec2 = resource_record_for(unprocessed_resource, nil, nil, :nothing, "unprocessed", "")
[ rec1, rec2 ]
end
let(:status) { "failure" }
diff --git a/spec/unit/resource/chocolatey_source_spec.rb b/spec/unit/resource/chocolatey_source_spec.rb
index 60bd773594..aad9c4c283 100644
--- a/spec/unit/resource/chocolatey_source_spec.rb
+++ b/spec/unit/resource/chocolatey_source_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2018, Chef Software, Inc.
+# Copyright:: Copyright 2018-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,9 +49,10 @@ describe Chef::Resource::ChocolateySource do
before(:each) do
disable_provider # vivify before mocking
enable_provider
+ current_resource
allow(resource).to receive(:provider_for_action).and_return(disable_provider)
allow(resource).to receive(:provider_for_action).and_return(enable_provider)
- allow(resource).to receive(:dup).and_return(current_resource)
+ allow(resource.class).to receive(:new).and_return(current_resource)
@original_env = ENV.to_hash
ENV["ALLUSERSPROFILE"] = 'C:\ProgramData'
end