diff options
author | John Keiser <john@johnkeiser.com> | 2015-07-03 14:16:32 -0600 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-07-03 14:16:32 -0600 |
commit | cfd2b1fa1b26e8b0aa92a5ba8bd294b96379b2fa (patch) | |
tree | d0715ed8eaed714460b168103ef39b748e85b8ba /spec | |
parent | ed2b0904361448173e5644dddacb48399fd8dc68 (diff) | |
parent | 78f72c82716acbd504f6974555cb45d61e895032 (diff) | |
download | chef-cfd2b1fa1b26e8b0aa92a5ba8bd294b96379b2fa.tar.gz |
Merge branch 'jk/property-state'
Diffstat (limited to 'spec')
-rw-r--r-- | spec/unit/mixin/params_validate_spec.rb | 6 | ||||
-rw-r--r-- | spec/unit/property/state_spec.rb | 654 | ||||
-rw-r--r-- | spec/unit/property/validation_spec.rb | 54 | ||||
-rw-r--r-- | spec/unit/property_spec.rb | 258 | ||||
-rw-r--r-- | spec/unit/resource_spec.rb | 4 |
5 files changed, 575 insertions, 401 deletions
diff --git a/spec/unit/mixin/params_validate_spec.rb b/spec/unit/mixin/params_validate_spec.rb index 85e1c1abab..3724bbf583 100644 --- a/spec/unit/mixin/params_validate_spec.rb +++ b/spec/unit/mixin/params_validate_spec.rb @@ -21,6 +21,8 @@ require 'spec_helper' class TinyClass include Chef::Mixin::ParamsValidate + attr_reader :name + def music(is_good=true) is_good end @@ -331,11 +333,11 @@ describe Chef::Mixin::ParamsValidate do it "asserts that a value returns false from a predicate method" do expect do @vo.validate({:not_blank => "should pass"}, - {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}}) + {:not_blank => {:cannot_be => [ :nil, :empty ]}}) end.not_to raise_error expect do @vo.validate({:not_blank => ""}, - {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}}) + {:not_blank => {:cannot_be => [ :nil, :empty ]}}) end.to raise_error(Chef::Exceptions::ValidationFailed) end diff --git a/spec/unit/property/state_spec.rb b/spec/unit/property/state_spec.rb index 80ebe01a41..bf2de178c9 100644 --- a/spec/unit/property/state_spec.rb +++ b/spec/unit/property/state_spec.rb @@ -50,20 +50,20 @@ describe "Chef::Resource#identity and #state" do end # identity - context "Chef::Resource#identity_attr" do + context "Chef::Resource#identity_properties" do with_property ":x" do - # it "name is the default identity" do - # expect(resource_class.identity_attr).to eq :name - # expect(resource_class.properties[:name].identity?).to be_falsey - # expect(resource.name).to eq 'blah' - # expect(resource.identity).to eq 'blah' - # end + it "name is the default identity" do + expect(resource_class.identity_properties).to eq [ Chef::Resource.properties[:name] ] + expect(Chef::Resource.properties[:name].identity?).to be_falsey + expect(resource.name).to eq 'blah' + expect(resource.identity).to eq 'blah' + end - it "identity_attr :x changes the identity" do - expect(resource_class.identity_attr :x).to eq :x - expect(resource_class.identity_attr).to eq :x - # expect(resource_class.properties[:name].identity?).to be_falsey - # expect(resource_class.properties[:x].identity?).to be_truthy + it "identity_properties :x changes the identity" do + expect(resource_class.identity_properties :x).to eq [ resource_class.properties[:x] ] + expect(resource_class.identity_properties).to eq [ resource_class.properties[:x] ] + expect(Chef::Resource.properties[:name].identity?).to be_falsey + expect(resource_class.properties[:x].identity?).to be_truthy expect(resource.x 'woo').to eq 'woo' expect(resource.x).to eq 'woo' @@ -72,28 +72,31 @@ describe "Chef::Resource#identity and #state" do expect(resource.identity).to eq 'woo' end - # with_property ":y, identity: true" do - # context "and identity_attr :x" do - # before do - # resource_class.class_eval do - # identity_attr :x - # end - # end - # - # it "only returns :x as identity" do - # resource.x 'foo' - # resource.y 'bar' - # expect(resource_class.identity_attr).to eq :x - # expect(resource.identity).to eq 'foo' - # end - # it "does not flip y.desired_state off" do - # resource.x 'foo' - # resource.y 'bar' - # expect(resource_class.state_attrs).to eq [ :x, :y ] - # expect(resource.state).to eq({ x: 'foo', y: 'bar' }) - # end - # end - # end + with_property ":y, identity: true" do + context "and identity_properties :x" do + before do + resource_class.class_eval do + identity_properties :x + end + end + + it "only returns :x as identity" do + resource.x 'foo' + resource.y 'bar' + expect(resource_class.identity_properties).to eq [ resource_class.properties[:x] ] + expect(resource.identity).to eq 'foo' + end + it "does not flip y.desired_state off" do + resource.x 'foo' + resource.y 'bar' + expect(resource_class.state_properties).to eq [ + resource_class.properties[:x], + resource_class.properties[:y] + ] + expect(resource.state_for_resource_reporter).to eq(x: 'foo', y: 'bar') + end + end + end context "With a subclass" do let(:subresource_class) do @@ -107,57 +110,63 @@ describe "Chef::Resource#identity and #state" do end it "name is the default identity on the subclass" do - # expect(subresource_class.identity_attr).to eq :name - # expect(subresource_class.properties[:name].identity?).to be_falsey + expect(subresource_class.identity_properties).to eq [ Chef::Resource.properties[:name] ] + expect(Chef::Resource.properties[:name].identity?).to be_falsey expect(subresource.name).to eq 'sub' expect(subresource.identity).to eq 'sub' end - context "With identity_attr :x on the superclass" do + context "With identity_properties :x on the superclass" do before do resource_class.class_eval do - identity_attr :x + identity_properties :x end end it "The subclass inherits :x as identity" do - expect(subresource_class.identity_attr).to eq :x - # expect(subresource_class.properties[:name].identity?).to be_falsey - # expect(subresource_class.properties[:x].identity?).to be_truthy + expect(subresource_class.identity_properties).to eq [ subresource_class.properties[:x] ] + expect(Chef::Resource.properties[:name].identity?).to be_falsey + expect(subresource_class.properties[:x].identity?).to be_truthy subresource.x 'foo' expect(subresource.identity).to eq 'foo' end - # context "With property :y, identity: true on the subclass" do - # before do - # subresource_class.class_eval do - # property :y, identity: true - # end - # end - # it "The subclass's identity includes both x and y" do - # expect(subresource_class.identity_attr).to eq :x - # subresource.x 'foo' - # subresource.y 'bar' - # expect(subresource.identity).to eq({ x: 'foo', y: 'bar' }) - # end - # end + context "With property :y, identity: true on the subclass" do + before do + subresource_class.class_eval do + property :y, identity: true + end + end + it "The subclass's identity includes both x and y" do + expect(subresource_class.identity_properties).to eq [ + subresource_class.properties[:x], + subresource_class.properties[:y] + ] + subresource.x 'foo' + subresource.y 'bar' + expect(subresource.identity).to eq(x: 'foo', y: 'bar') + end + end with_property ":y, String" do - context "With identity_attr :y on the subclass" do + context "With identity_properties :y on the subclass" do before do subresource_class.class_eval do - identity_attr :y + identity_properties :y end end - # it "y is part of state" do - # subresource.x 'foo' - # subresource.y 'bar' - # expect(subresource.state).to eq({ x: 'foo', y: 'bar' }) - # expect(subresource_class.state_attrs).to eq [ :x, :y ] - # end + it "y is part of state" do + subresource.x 'foo' + subresource.y 'bar' + expect(subresource.state_for_resource_reporter).to eq(x: 'foo', y: 'bar') + expect(subresource_class.state_properties).to eq [ + subresource_class.properties[:x], + subresource_class.properties[:y] + ] + end it "y is the identity" do - expect(subresource_class.identity_attr).to eq :y + expect(subresource_class.identity_properties).to eq [ subresource_class.properties[:y] ] subresource.x 'foo' subresource.y 'bar' expect(subresource.identity).to eq 'bar' @@ -171,24 +180,24 @@ describe "Chef::Resource#identity and #state" do end end - # with_property ":string_only, String, identity: true", ":string_only2, String" do - # it "identity_attr does not change validation" do - # resource_class.identity_attr :string_only - # expect { resource.string_only 12 }.to raise_error Chef::Exceptions::ValidationFailed - # expect { resource.string_only2 12 }.to raise_error Chef::Exceptions::ValidationFailed - # end - # end - # - # with_property ":x, desired_state: false" do - # it "identity_attr does not flip on desired_state" do - # resource_class.identity_attr :x - # resource.x 'hi' - # expect(resource.identity).to eq 'hi' - # # expect(resource_class.properties[:x].desired_state?).to be_falsey - # expect(resource_class.state_attrs).to eq [] - # expect(resource.state).to eq({}) - # end - # end + with_property ":string_only, String, identity: true", ":string_only2, String" do + it "identity_properties does not change validation" do + resource_class.identity_properties :string_only + expect { resource.string_only 12 }.to raise_error Chef::Exceptions::ValidationFailed + expect { resource.string_only2 12 }.to raise_error Chef::Exceptions::ValidationFailed + end + end + + with_property ":x, desired_state: false" do + it "identity_properties does not change desired_state" do + resource_class.identity_properties :x + resource.x 'hi' + expect(resource.identity).to eq 'hi' + expect(resource_class.properties[:x].desired_state?).to be_falsey + expect(resource_class.state_properties).to eq [] + expect(resource.state_for_resource_reporter).to eq({}) + end + end context "With custom property custom_property defined only as methods, using different variables for storage" do before do @@ -202,24 +211,26 @@ describe "Chef::Resource#identity and #state" do end end - context "And identity_attr :custom_property" do + context "And identity_properties :custom_property" do before do resource_class.class_eval do - identity_attr :custom_property + identity_properties :custom_property end end - it "identity_attr comes back as :custom_property" do - # expect(resource_class.properties[:custom_property].identity?).to be_truthy - expect(resource_class.identity_attr).to eq :custom_property + it "identity_properties comes back as :custom_property" do + expect(resource_class.properties[:custom_property].identity?).to be_truthy + expect(resource_class.identity_properties).to eq [ resource_class.properties[:custom_property] ] + end + it "custom_property becomes part of desired_state" do + resource.custom_property = 1 + expect(resource.state_for_resource_reporter).to eq(custom_property: 6) + expect(resource_class.properties[:custom_property].desired_state?).to be_truthy + expect(resource_class.state_properties).to eq [ + resource_class.properties[:custom_property] + ] end - # it "custom_property becomes part of desired_state" do - # resource.custom_property = 1 - # expect(resource.state).to eq({ custom_property: 6 }) - # expect(resource_class.properties[:custom_property].desired_state?).to be_truthy - # expect(resource_class.state_attrs).to eq [ :custom_property ] - # end - it "identity_attr does not change custom_property's getter or setter" do + it "identity_properties does not change custom_property's getter or setter" do resource.custom_property = 1 expect(resource.custom_property).to eq 6 end @@ -232,111 +243,111 @@ describe "Chef::Resource#identity and #state" do end end - # context "PropertyType#identity" do - # with_property ":x, identity: true" do - # it "name is only part of the identity if an identity attribute is defined" do - # expect(resource_class.identity_attr).to eq :x - # resource.x 'woo' - # expect(resource.identity).to eq 'woo' - # end - # end - # - # with_property ":x, identity: true, default: 'xxx'", - # ":y, identity: true, default: 'yyy'", - # ":z, identity: true, default: 'zzz'" do - # it "identity_attr returns the first identity attribute if multiple are defined" do - # expect(resource_class.identity_attr).to eq :x - # end - # it "identity returns all identity values in a hash if multiple are defined" do - # resource.x 'foo' - # resource.y 'bar' - # resource.z 'baz' - # expect(resource.identity).to eq({ x: 'foo', y: 'bar', z: 'baz' }) - # end - # it "identity returns only identity values that are set, and does not include defaults" do - # resource.x 'foo' - # resource.z 'baz' - # expect(resource.identity).to eq({ x: 'foo', z: 'baz' }) - # end - # it "identity returns only set identity values in a hash, if there is only one set identity value" do - # resource.x 'foo' - # expect(resource.identity).to eq({ x: 'foo' }) - # end - # it "identity returns an empty hash if no identity values are set" do - # expect(resource.identity).to eq({}) - # end - # it "identity_attr wipes out any other identity attributes if multiple are defined" do - # resource_class.identity_attr :y - # resource.x 'foo' - # resource.y 'bar' - # resource.z 'baz' - # expect(resource.identity).to eq 'bar' - # end - # end - # - # with_property ":x, identity: true, name_property: true" do - # it "identity when x is not defined returns the value of x" do - # expect(resource.identity).to eq 'blah' - # end - # it "state when x is not defined returns the value of x" do - # expect(resource.state).to eq({ x: 'blah' }) - # end - # end - # end - - # state_attrs - context "Chef::Resource#state_attrs" do - it "name is not part of state_attrs" do - expect(Chef::Resource.state_attrs).to eq [] - expect(resource_class.state_attrs).to eq [] - expect(resource.state).to eq({}) + context "Property#identity" do + with_property ":x, identity: true" do + it "name is only part of the identity if an identity attribute is defined" do + expect(resource_class.identity_properties).to eq [ resource_class.properties[:x] ] + resource.x 'woo' + expect(resource.identity).to eq 'woo' + end + end + + with_property ":x, identity: true, default: 'xxx'", + ":y, identity: true, default: 'yyy'", + ":z, identity: true, default: 'zzz'" do + it "identity_property raises an error if multiple identity values are defined" do + expect { resource_class.identity_property }.to raise_error Chef::Exceptions::MultipleIdentityError + end + it "identity_attr raises an error if multiple identity values are defined" do + expect { resource_class.identity_attr }.to raise_error Chef::Exceptions::MultipleIdentityError + end + it "identity returns all identity values in a hash if multiple are defined" do + resource.x 'foo' + resource.y 'bar' + resource.z 'baz' + expect(resource.identity).to eq(x: 'foo', y: 'bar', z: 'baz') + end + it "identity returns all values whether any value is set or not" do + expect(resource.identity).to eq(x: 'xxx', y: 'yyy', z: 'zzz') + end + it "identity_properties wipes out any other identity attributes if multiple are defined" do + resource_class.identity_properties :y + resource.x 'foo' + resource.y 'bar' + resource.z 'baz' + expect(resource.identity).to eq 'bar' + end + end + + with_property ":x, identity: true, name_property: true" do + it "identity when x is not defined returns the value of x" do + expect(resource.identity).to eq 'blah' + end + it "state when x is not defined returns the value of x" do + expect(resource.state_for_resource_reporter).to eq(x: 'blah') + end end + end - # with_property ":x", ":y", ":z" do - # it "x, y and z are state attributes" do - # resource.x 1 - # resource.y 2 - # resource.z 3 - # expect(resource_class.state_attrs).to eq [ :x, :y, :z ] - # expect(resource.state).to eq(x: 1, y: 2, z: 3) - # end - # it "values that are not set are not included in state" do - # resource.x 1 - # expect(resource.state).to eq(x: 1) - # end - # it "when no values are set, nothing is included in state" do - # end - # end - # - # with_property ":x", ":y, desired_state: false", ":z, desired_state: true" do - # it "x and z are state attributes, and y is not" do - # resource.x 1 - # resource.y 2 - # resource.z 3 - # expect(resource_class.state_attrs).to eq [ :x, :z ] - # expect(resource.state).to eq(x: 1, z: 3) - # end - # end - - # with_property ":x, name_property: true" do - # it "Unset values with name_property are included in state" do - # expect(resource.state).to eq(x: 'blah') - # end - # it "Set values with name_property are included in state" do - # resource.x 1 - # expect(resource.state).to eq(x: 1) - # end - # end - - # with_property ":x, default: 1" do - # it "Unset values with defaults are not included in state" do - # expect(resource.state).to eq({}) - # end - # it "Set values with defaults are included in state" do - # resource.x 1 - # expect(resource.state).to eq(x: 1) - # end - # end + # state_properties + context "Chef::Resource#state_properties" do + it "state_properties is empty by default" do + expect(Chef::Resource.state_properties).to eq [] + expect(resource.state_for_resource_reporter).to eq({}) + end + + with_property ":x", ":y", ":z" do + it "x, y and z are state attributes" do + resource.x 1 + resource.y 2 + resource.z 3 + expect(resource_class.state_properties).to eq [ + resource_class.properties[:x], + resource_class.properties[:y], + resource_class.properties[:z] + ] + expect(resource.state_for_resource_reporter).to eq(x: 1, y: 2, z: 3) + end + it "values that are not set are not included in state" do + resource.x 1 + expect(resource.state_for_resource_reporter).to eq(x: 1) + end + it "when no values are set, nothing is included in state" do + end + end + + with_property ":x", ":y, desired_state: false", ":z, desired_state: true" do + it "x and z are state attributes, and y is not" do + resource.x 1 + resource.y 2 + resource.z 3 + expect(resource_class.state_properties).to eq [ + resource_class.properties[:x], + resource_class.properties[:z] + ] + expect(resource.state_for_resource_reporter).to eq(x: 1, z: 3) + end + end + + with_property ":x, name_property: true" do + # it "Unset values with name_property are included in state" do + # expect(resource.state_for_resource_reporter).to eq({ x: 'blah' }) + # end + it "Set values with name_property are included in state" do + resource.x 1 + expect(resource.state_for_resource_reporter).to eq(x: 1) + end + end + + with_property ":x, default: 1" do + it "Unset values with defaults are not included in state" do + expect(resource.state_for_resource_reporter).to eq({}) + end + it "Set values with defaults are included in state" do + resource.x 1 + expect(resource.state_for_resource_reporter).to eq(x: 1) + end + end context "With a class with a normal getter and setter" do before do @@ -349,143 +360,132 @@ describe "Chef::Resource#identity and #state" do end end end - it "state_attrs(:x) causes the value to be included in properties" do - resource_class.state_attrs(:x) + it "state_properties(:x) causes the value to be included in properties" do + resource_class.state_properties(:x) resource.x = 1 expect(resource.x).to eq 6 - expect(resource.state).to eq(x: 6) + expect(resource.state_for_resource_reporter).to eq(x: 6) end end - # with_property ":x, Integer, identity: true" do - # it "state_attrs(:x) leaves the property in desired_state" do - # resource_class.state_attrs(:x) - # resource.x 10 - # - # # expect(resource_class.properties[:x].desired_state?).to be_truthy - # expect(resource_class.state_attrs).to eq [ :x ] - # expect(resource.state).to eq(x: 10) - # end - # it "state_attrs(:x) does not turn off validation" do - # resource_class.state_attrs(:x) - # expect { resource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed - # end - # it "state_attrs(:x) does not turn off identity" do - # resource_class.state_attrs(:x) - # resource.x 10 - # - # expect(resource_class.identity_attr).to eq :x - # # expect(resource_class.properties[:x].identity?).to be_truthy - # expect(resource.identity).to eq 10 - # end - # end - - # with_property ":x, Integer, identity: true, desired_state: false" do - # before do - # resource_class.class_eval do - # def y - # 20 - # end - # end - # end - # it "state_attrs(:x) sets the property in desired_state" do - # resource_class.state_attrs(:x) - # resource.x 10 - # - # # expect(resource_class.properties[:x].desired_state?).to be_truthy - # expect(resource_class.state_attrs).to eq [ :x ] - # expect(resource.state).to eq(x: 10) - # end - # it "state_attrs(:x) does not turn off validation" do - # resource_class.state_attrs(:x) - # expect { resource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed - # end - # it "state_attrs(:x) does not turn off identity" do - # resource_class.state_attrs(:x) - # resource.x 10 - # - # expect(resource_class.identity_attr).to eq :x - # # expect(resource_class.properties[:x].identity?).to be_truthy - # expect(resource.identity).to eq 10 - # end - # it "state_attrs(:y) adds y and removes x from desired state" do - # resource_class.state_attrs(:y) - # resource.x 10 - # - # # expect(resource_class.properties[:x].desired_state?).to be_falsey - # # expect(resource_class.properties[:y].desired_state?).to be_truthy - # expect(resource_class.state_attrs).to eq [ :y ] - # expect(resource.state).to eq(y: 20) - # end - # it "state_attrs(:y) does not turn off validation" do - # resource_class.state_attrs(:y) - # - # expect { resource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed - # end - # it "state_attrs(:y) does not turn off identity" do - # resource_class.state_attrs(:y) - # resource.x 10 - # - # expect(resource_class.identity_attr).to eq :x - # # expect(resource_class.properties[:x].identity?).to be_truthy - # expect(resource.identity).to eq 10 - # end - # - # context "With a subclassed resource" do - # let(:resource_subclass) do - # new_resource_name = self.class.new_resource_name - # Class.new(resource_class) do - # resource_name new_resource_name - # end - # end - # let(:subresource) do - # resource_subclass.new('blah') - # end - # it "state_attrs(:x) sets the property in desired_state" do - # resource_subclass.state_attrs(:x) - # subresource.x 10 - # - # # expect(resource_subclass.properties[:x].desired_state?).to be_truthy - # expect(resource_subclass.state_attrs).to eq [ :x ] - # expect(subresource.state).to eq(x: 10) - # end - # it "state_attrs(:x) does not turn off validation" do - # resource_subclass.state_attrs(:x) - # expect { subresource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed - # end - # it "state_attrs(:x) does not turn off identity" do - # resource_subclass.state_attrs(:x) - # subresource.x 10 - # - # expect(resource_subclass.identity_attr).to eq :x - # # expect(resource_subclass.properties[:x].identity?).to be_truthy - # expect(subresource.identity).to eq 10 - # end - # it "state_attrs(:y) adds y and removes x from desired state" do - # resource_subclass.state_attrs(:y) - # subresource.x 10 - # - # # expect(resource_subclass.properties[:x].desired_state?).to be_falsey - # # expect(resource_subclass.properties[:y].desired_state?).to be_truthy - # expect(resource_subclass.state_attrs).to eq [ :y ] - # expect(subresource.state).to eq(y: 20) - # end - # it "state_attrs(:y) does not turn off validation" do - # resource_subclass.state_attrs(:y) - # - # expect { subresource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed - # end - # it "state_attrs(:y) does not turn off identity" do - # resource_subclass.state_attrs(:y) - # subresource.x 10 - # - # expect(resource_subclass.identity_attr).to eq :x - # # expect(resource_subclass.properties[:x].identity?).to be_truthy - # expect(subresource.identity).to eq 10 - # end - # end - # end + with_property ":x, Integer, identity: true" do + it "state_properties(:x) leaves the property in desired_state" do + resource_class.state_properties(:x) + resource.x 10 + + expect(resource_class.properties[:x].desired_state?).to be_truthy + expect(resource_class.state_properties).to eq [ + resource_class.properties[:x] + ] + expect(resource.state_for_resource_reporter).to eq(x: 10) + end + it "state_properties(:x) does not turn off validation" do + resource_class.state_properties(:x) + expect { resource.x 'ouch' }.to raise_error Chef::Exceptions::ValidationFailed + end + it "state_properties(:x) does not turn off identity" do + resource_class.state_properties(:x) + resource.x 10 + + expect(resource_class.identity_properties).to eq [ resource_class.properties[:x] ] + expect(resource_class.properties[:x].identity?).to be_truthy + expect(resource.identity).to eq 10 + end + end + + with_property ":x, Integer, identity: true, desired_state: false" do + before do + resource_class.class_eval do + def y + 20 + end + end + end + + it "state_properties(:x) leaves x identical" do + old_value = resource_class.properties[:y] + resource_class.state_properties(:x) + resource.x 10 + + expect(resource_class.properties[:y].object_id).to eq old_value.object_id + + expect(resource_class.properties[:x].desired_state?).to be_truthy + expect(resource_class.properties[:x].identity?).to be_truthy + expect(resource_class.identity_properties).to eq [ + resource_class.properties[:x] + ] + expect(resource.identity).to eq(10) + expect(resource_class.state_properties).to eq [ + resource_class.properties[:x] + ] + expect(resource.state_for_resource_reporter).to eq(x: 10) + end + + it "state_properties(:y) adds y to desired state" do + old_value = resource_class.properties[:x] + resource_class.state_properties(:y) + resource.x 10 + + expect(resource_class.properties[:x].object_id).to eq old_value.object_id + expect(resource_class.properties[:x].desired_state?).to be_falsey + expect(resource_class.properties[:y].desired_state?).to be_truthy + expect(resource_class.state_properties).to eq [ + resource_class.properties[:y] + ] + expect(resource.state_for_resource_reporter).to eq(y: 20) + end + + context "With a subclassed resource" do + let(:subresource_class) do + new_resource_name = self.class.new_resource_name + Class.new(resource_class) do + resource_name new_resource_name + end + end + let(:subresource) do + subresource_class.new('blah') + end + + it "state_properties(:x) adds x to desired state" do + old_value = resource_class.properties[:y] + subresource_class.state_properties(:x) + subresource.x 10 + + expect(subresource_class.properties[:y].object_id).to eq old_value.object_id + + expect(subresource_class.properties[:x].desired_state?).to be_truthy + expect(subresource_class.properties[:x].identity?).to be_truthy + expect(subresource_class.identity_properties).to eq [ + subresource_class.properties[:x] + ] + expect(subresource.identity).to eq(10) + expect(subresource_class.state_properties).to eq [ + subresource_class.properties[:x] + ] + expect(subresource.state_for_resource_reporter).to eq(x: 10) + end + + it "state_properties(:y) adds y to desired state" do + old_value = resource_class.properties[:x] + subresource_class.state_properties(:y) + subresource.x 10 + + expect(subresource_class.properties[:x].object_id).to eq old_value.object_id + expect(subresource_class.properties[:y].desired_state?).to be_truthy + expect(subresource_class.state_properties).to eq [ + subresource_class.properties[:y] + ] + expect(subresource.state_for_resource_reporter).to eq(y: 20) + + expect(subresource_class.properties[:x].identity?).to be_truthy + expect(subresource_class.identity_properties).to eq [ + subresource_class.properties[:x] + ] + expect(subresource.identity).to eq(10) + end + end + end end end diff --git a/spec/unit/property/validation_spec.rb b/spec/unit/property/validation_spec.rb index 7ce6a45167..a3649d228c 100644 --- a/spec/unit/property/validation_spec.rb +++ b/spec/unit/property/validation_spec.rb @@ -111,10 +111,6 @@ describe "Chef::Resource.property validation" do it "get succeeds" do expect(resource.x).to eq 'default' end - it "set(nil) = get" do - expect(resource.x nil).to eq 'default' - expect(resource.x).to eq 'default' - end it "set to valid value succeeds" do expect(resource.x 'str').to eq 'str' expect(resource.x).to eq 'str' @@ -122,15 +118,18 @@ describe "Chef::Resource.property validation" do it "set to invalid value raises ValidationFailed" do expect { resource.x 10 }.to raise_error Chef::Exceptions::ValidationFailed end + it "set to nil emits a deprecation warning and does a get" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + Chef::Config[:treat_deprecation_warnings_as_errors] = false + resource.x 'str' + expect(resource.x nil).to eq 'str' + expect(resource.x).to eq 'str' + end end context "when the variable does not have an initial value" do it "get succeeds" do expect(resource.x).to be_nil end - it "set(nil) = get" do - expect(resource.x nil).to be_nil - expect(resource.x).to be_nil - end it "set to valid value succeeds" do expect(resource.x 'str').to eq 'str' expect(resource.x).to eq 'str' @@ -138,6 +137,13 @@ describe "Chef::Resource.property validation" do it "set to invalid value raises ValidationFailed" do expect { resource.x 10 }.to raise_error Chef::Exceptions::ValidationFailed end + it "set to nil emits a deprecation warning and does a get" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + Chef::Config[:treat_deprecation_warnings_as_errors] = false + resource.x 'str' + expect(resource.x nil).to eq 'str' + expect(resource.x).to eq 'str' + end end end with_property ":x, [ String, nil ]" do @@ -255,10 +261,10 @@ describe "Chef::Resource.property validation" do [ '', 'abac' ], [ nil ] - # PropertyType - # validation_test 'is: PropertyType.new(is: :a)', - # [ :a ], - # [ :b, nil ] + # Property + validation_test 'is: Chef::Property.new(is: :a)', + [ :a ], + [ :b, nil ] # RSpec Matcher class Globalses @@ -523,10 +529,11 @@ describe "Chef::Resource.property validation" do expect(resource.x 1).to eq 1 expect(resource.x).to eq 1 end - it "value nil does a get" do + it "value nil emits a deprecation warning and does a get" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError Chef::Config[:treat_deprecation_warnings_as_errors] = false resource.x 1 - resource.x nil + expect(resource.x nil).to eq 1 expect(resource.x).to eq 1 end end @@ -549,16 +556,18 @@ describe "Chef::Resource.property validation" do end with_property ':x, name_property: true, required: true' do - it "if x is not specified, retrieval succeeds" do + it "if x is not specified, the name property is returned" do expect(resource.x).to eq 'blah' end it "value 1 is valid" do expect(resource.x 1).to eq 1 expect(resource.x).to eq 1 end - it "value nil does a get" do + it "value nil emits a deprecation warning and does a get" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + Chef::Config[:treat_deprecation_warnings_as_errors] = false resource.x 1 - resource.x nil + expect(resource.x nil).to eq 1 expect(resource.x).to eq 1 end end @@ -571,9 +580,11 @@ describe "Chef::Resource.property validation" do expect(resource.x 1).to eq 1 expect(resource.x).to eq 1 end - it "value nil does a get" do + it "value nil is invalid" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + Chef::Config[:treat_deprecation_warnings_as_errors] = false resource.x 1 - resource.x nil + expect(resource.x nil).to eq 1 expect(resource.x).to eq 1 end end @@ -596,11 +607,6 @@ describe "Chef::Resource.property validation" do end end - # it "getting the value causes a deprecation warning" do - # Chef::Config[:treat_deprecation_warnings_as_errors] = true - # expect { resource.x }.to raise_error Chef::Exceptions::DeprecatedFeatureError - # end - it "value 1 is valid" do expect(resource.x 1).to eq 1 expect(resource.x).to eq 1 diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb index ce0552c564..09f7e52329 100644 --- a/spec/unit/property_spec.rb +++ b/spec/unit/property_spec.rb @@ -58,11 +58,15 @@ describe "Chef::Resource.property" do else tags = [] end - properties = properties.map { |property| "property #{property}" } - context "With properties #{english_join(properties)}", *tags do + if properties.size == 1 + description = "With property #{properties.first}" + else + description = "With properties #{english_join(properties.map { |property| "#{property.inspect}" })}" + end + context description, *tags do before do properties.each do |property_str| - resource_class.class_eval(property_str, __FILE__, __LINE__) + resource_class.class_eval("property #{property_str}", __FILE__, __LINE__) end end instance_eval(&block) @@ -75,11 +79,10 @@ describe "Chef::Resource.property" do expect(resource.bare_property 10).to eq 10 expect(resource.bare_property).to eq 10 end - # it "emits a deprecation warning and does a get, if set to nil" do it "emits a deprecation warning and does a get, if set to nil" do expect(resource.bare_property 10).to eq 10 - # expect { resource.bare_property nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError - # Chef::Config[:treat_deprecation_warnings_as_errors] = false + expect { resource.bare_property nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError + Chef::Config[:treat_deprecation_warnings_as_errors] = false expect(resource.bare_property nil).to eq 10 expect(resource.bare_property).to eq 10 end @@ -92,11 +95,11 @@ describe "Chef::Resource.property" do expect(resource.bare_property 10).to eq 10 expect(resource.bare_property).to eq 10 end - # it "can be set to nil with =" do - # expect(resource.bare_property 10).to eq 10 - # expect(resource.bare_property = nil).to be_nil - # expect(resource.bare_property).to be_nil - # end + it "can be set to nil with =" do + expect(resource.bare_property 10).to eq 10 + expect(resource.bare_property = nil).to be_nil + expect(resource.bare_property).to be_nil + end it "can be updated with =" do expect(resource.bare_property 10).to eq 10 expect(resource.bare_property = 20).to eq 20 @@ -121,7 +124,7 @@ describe "Chef::Resource.property" do expect(subresource.x).to eq 10 expect(subresource.x = 20).to eq 20 expect(subresource.x).to eq 20 - # expect(subresource_class.properties[:x]).not_to be_nil + expect(subresource_class.properties[:x]).not_to be_nil end it "x's validation is inherited" do @@ -140,18 +143,18 @@ describe "Chef::Resource.property" do expect(subresource.x).to eq 10 expect(subresource.x = 20).to eq 20 expect(subresource.x).to eq 20 - # expect(subresource_class.properties[:x]).not_to be_nil + expect(subresource_class.properties[:x]).not_to be_nil end it "y is there" do expect(subresource.y 10).to eq 10 expect(subresource.y).to eq 10 expect(subresource.y = 20).to eq 20 expect(subresource.y).to eq 20 - # expect(subresource_class.properties[:y]).not_to be_nil + expect(subresource_class.properties[:y]).not_to be_nil end it "y is not on the superclass" do expect { resource_class.y 10 }.to raise_error - # expect(resource_class.properties[:y]).to be_nil + expect(resource_class.properties[:y]).to be_nil end end @@ -167,17 +170,37 @@ describe "Chef::Resource.property" do expect(subresource.x).to eq 10 expect(subresource.x = 20).to eq 20 expect(subresource.x).to eq 20 - # expect(subresource_class.properties[:x]).not_to be_nil - # expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] + expect(subresource_class.properties[:x]).not_to be_nil + expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] end - it "x's validation is overwritten" do - expect(subresource.x 'ohno').to eq 'ohno' - expect(subresource.x).to eq 'ohno' + it "x's validation is inherited" do + expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed end + end - it "the superclass's validation for x is still there" do - expect { resource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed + context "with property :x, default: 80 on the subclass" do + before do + subresource_class.class_eval do + property :x, default: 80 + end + end + + it "x is still there" do + expect(subresource.x 10).to eq 10 + expect(subresource.x).to eq 10 + expect(subresource.x = 20).to eq 20 + expect(subresource.x).to eq 20 + expect(subresource_class.properties[:x]).not_to be_nil + expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] + end + + it "x defaults to 80" do + expect(subresource.x).to eq 80 + end + + it "x's validation is inherited" do + expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed end end @@ -193,8 +216,8 @@ describe "Chef::Resource.property" do expect(subresource.x).to eq "10" expect(subresource.x = "20").to eq "20" expect(subresource.x).to eq "20" - # expect(subresource_class.properties[:x]).not_to be_nil - # expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] + expect(subresource_class.properties[:x]).not_to be_nil + expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x] end it "x's validation is overwritten" do @@ -212,14 +235,89 @@ describe "Chef::Resource.property" do end end - context "Chef::Resource::PropertyType#property_is_set?" do + context "Chef::Resource::Property#reset_property" do + it "when a resource is newly created, reset_property(:name) sets property to nil" do + expect(resource.property_is_set?(:name)).to be_truthy + resource.reset_property(:name) + expect(resource.property_is_set?(:name)).to be_falsey + expect(resource.name).to be_nil + end + + it "when referencing an undefined property, reset_property(:x) raises an error" do + expect { resource.reset_property(:x) }.to raise_error(ArgumentError) + end + + with_property ':x' do + it "when the resource is newly created, reset_property(:x) does nothing" do + expect(resource.property_is_set?(:x)).to be_falsey + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to be_nil + end + it "when x is set, reset_property resets it" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to be_nil + end + end + + with_property ':x, Integer' do + it "when the resource is newly created, reset_property(:x) does nothing" do + expect(resource.property_is_set?(:x)).to be_falsey + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to be_nil + end + it "when x is set, reset_property resets it even though `nil` is technically invalid" do + resource.x 10 + expect(resource.property_is_set?(:x)).to be_truthy + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to be_nil + end + end + + with_property ':x, default: 10' do + it "when the resource is newly created, reset_property(:x) does nothing" do + expect(resource.property_is_set?(:x)).to be_falsey + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to eq 10 + end + it "when x is set, reset_property resets it and it returns the default" do + resource.x 20 + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to eq 10 + end + end + + with_property ':x, default: lazy { 10 }' do + it "when the resource is newly created, reset_property(:x) does nothing" do + expect(resource.property_is_set?(:x)).to be_falsey + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to eq 10 + end + it "when x is set, reset_property resets it and it returns the default" do + resource.x 20 + resource.reset_property(:x) + expect(resource.property_is_set?(:x)).to be_falsey + expect(resource.x).to eq 10 + end + end + end + + context "Chef::Resource::Property#property_is_set?" do it "when a resource is newly created, property_is_set?(:name) is true" do expect(resource.property_is_set?(:name)).to be_truthy end - # it "when referencing an undefined property, property_is_set?(:x) raises an error" do - # expect { resource.property_is_set?(:x) }.to raise_error(ArgumentError) - # end + it "when referencing an undefined property, property_is_set?(:x) raises an error" do + expect { resource.property_is_set?(:x) }.to raise_error(ArgumentError) + end with_property ':x' do it "when the resource is newly created, property_is_set?(:x) is false" do @@ -259,9 +357,9 @@ describe "Chef::Resource.property" do resource.x lazy { 10 } expect(resource.property_is_set?(:x)).to be_truthy end - it "when x is retrieved, property_is_set?(:x) is true" do + it "when x is retrieved, property_is_set?(:x) is false" do resource.x - expect(resource.property_is_set?(:x)).to be_truthy + expect(resource.property_is_set?(:x)).to be_falsey end end @@ -281,9 +379,9 @@ describe "Chef::Resource.property" do resource.x lazy { 10 } expect(resource.property_is_set?(:x)).to be_truthy end - it "when x is retrieved, property_is_set?(:x) is true" do + it "when x is retrieved, property_is_set?(:x) is false" do resource.x - expect(resource.property_is_set?(:x)).to be_truthy + expect(resource.property_is_set?(:x)).to be_falsey end end @@ -299,14 +397,14 @@ describe "Chef::Resource.property" do resource.x = 10 expect(resource.property_is_set?(:x)).to be_truthy end - it "when x is retrieved, property_is_set?(:x) is true" do + it "when x is retrieved, property_is_set?(:x) is false" do resource.x - expect(resource.property_is_set?(:x)).to be_truthy + expect(resource.property_is_set?(:x)).to be_falsey end end end - context "Chef::Resource::PropertyType#default" do + context "Chef::Resource::Property#default" do with_property ':x, default: 10' do it "when x is set, it returns its value" do expect(resource.x 20).to eq 20 @@ -317,7 +415,7 @@ describe "Chef::Resource.property" do expect(resource.x).to eq 10 end it "when x is not set, it is not included in state" do - expect(resource.state).to eq({}) + expect(resource.state_for_resource_reporter).to eq({}) end it "when x is set to nil, it returns nil" do resource.instance_eval { @x = nil } @@ -339,8 +437,15 @@ describe "Chef::Resource.property" do end with_property ':x, default: 10, identity: true' do - it "when x is not set, it is not included in identity" do - expect(resource.state).to eq({}) + it "when x is not set, it is included in identity" do + expect(resource.identity).to eq(10) + end + end + + with_property ':x, default: 1, identity: true', ':y, default: 2, identity: true' do + it "when x is not set, it is still included in identity" do + resource.y 20 + expect(resource.identity).to eq(x: 1, y: 20) end end @@ -462,21 +567,35 @@ describe "Chef::Resource.property" do # end end - with_property ":x, default: lazy { Namer.next_index }, is: proc { |v| Namer.next_index; true }" do + with_property ":x, default: lazy { Namer.next_index.to_s }, is: proc { |v| Namer.next_index; true }" do it "validation is not run at all on the default value" do - expect(resource.x).to eq 1 + expect(resource.x).to eq '1' + expect(Namer.current_index).to eq 1 + end + # it "validation is run each time" do + # expect(resource.x).to eq '1' + # expect(Namer.current_index).to eq 2 + # expect(resource.x).to eq '1' + # expect(Namer.current_index).to eq 2 + # end + end + + with_property ":x, default: lazy { Namer.next_index.to_s.freeze }, is: proc { |v| Namer.next_index; true }" do + it "validation is not run at all on the default value" do + expect(resource.x).to eq '1' expect(Namer.current_index).to eq 1 end # it "validation is only run the first time" do - # expect(resource.x).to eq 1 + # expect(resource.x).to eq '1' # expect(Namer.current_index).to eq 2 - # expect(resource.x).to eq 1 + # expect(resource.x).to eq '1' # expect(Namer.current_index).to eq 2 # end end end context "coercion of defaults" do + # Frozen default, non-frozen coerce with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do it "when the resource is created, the proc is not yet run" do resource @@ -487,13 +606,32 @@ describe "Chef::Resource.property" do expect(resource.x).to eq 'hi1' expect(Namer.current_index).to eq 1 end - it "when x is retrieved, coercion is run, no more than once" do + it "when x is retrieved, coercion is run exactly once" do expect(resource.x).to eq '101' expect(resource.x).to eq '101' expect(Namer.current_index).to eq 1 end end + # Frozen default, frozen coerce + with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: 10' do + it "when the resource is created, the proc is not yet run" do + resource + expect(Namer.current_index).to eq 0 + end + it "when x is set, coercion is run" do + expect(resource.x 'hi').to eq 'hi1' + expect(resource.x).to eq 'hi1' + expect(Namer.current_index).to eq 1 + end + it "when x is retrieved, coercion is run each time" do + expect(resource.x).to eq '101' + expect(resource.x).to eq '102' + expect(Namer.current_index).to eq 2 + end + end + + # Frozen lazy default, non-frozen coerce with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do it "when the resource is created, the proc is not yet run" do resource @@ -504,6 +642,29 @@ describe "Chef::Resource.property" do expect(resource.x).to eq 'hi1' expect(Namer.current_index).to eq 1 end + it "when x is retrieved, coercion is run exactly once" do + expect(resource.x).to eq '101' + expect(resource.x).to eq '101' + expect(Namer.current_index).to eq 1 + end + end + + # Non-frozen lazy default, frozen coerce + with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: lazy { "10" }' do + it "when the resource is created, the proc is not yet run" do + resource + expect(Namer.current_index).to eq 0 + end + it "when x is set, coercion is run" do + expect(resource.x 'hi').to eq 'hi1' + expect(resource.x).to eq 'hi1' + expect(Namer.current_index).to eq 1 + end + it "when x is retrieved, coercion is run each time" do + expect(resource.x).to eq '101' + expect(resource.x).to eq '102' + expect(Namer.current_index).to eq 2 + end end with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do @@ -706,7 +867,7 @@ describe "Chef::Resource.property" do end end - context "Chef::Resource::PropertyType#coerce" do + context "Chef::Resource::Property#coerce" do with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do it "coercion runs on set" do expect(resource.x 10).to eq "101" @@ -740,7 +901,7 @@ describe "Chef::Resource.property" do end end - context "Chef::Resource::PropertyType validation" do + context "Chef::Resource::Property validation" do with_property ':x, is: proc { |v| Namer.next_index; v.is_a?(Integer) }' do it "validation runs on set" do expect(resource.x 10).to eq 10 @@ -768,7 +929,7 @@ describe "Chef::Resource.property" do end [ 'name_attribute', 'name_property' ].each do |name| - context "Chef::Resource::PropertyType##{name}" do + context "Chef::Resource::Property##{name}" do with_property ":x, #{name}: true" do it "defaults x to resource.name" do expect(resource.x).to eq 'blah' @@ -797,6 +958,11 @@ describe "Chef::Resource.property" do expect(resource.x).to eq 10 end end + with_property ":x, #{name}: true, required: true" do + it "defaults x to resource.name" do + expect(resource.x).to eq 'blah' + end + end end end end diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index 353c5ec129..1377950c99 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -59,8 +59,8 @@ describe Chef::Resource do end describe "when declaring the identity attribute" do - it "has no identity attribute by default" do - expect(Chef::Resource.identity_attr).to be_nil + it "has :name as identity attribute by default" do + expect(Chef::Resource.identity_attr).to eq(:name) end it "sets an identity attribute" do |