diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2021-02-23 15:55:45 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2021-02-25 16:54:23 -0800 |
commit | ba0a45460355014a2b7883bea0cabe5737f79fde (patch) | |
tree | f4308fa8063ded18060207e829423c1e8bb050e2 /spec | |
parent | 6fb4dae4f722ee28e17d6b4354c3b6f3fb01946e (diff) | |
download | chef-ba0a45460355014a2b7883bea0cabe5737f79fde.tar.gz |
Dup default property values
This largely makes frozen default value errors go away. Each
copy of a resource will get a dup of the default. Defaults are
still frozen so we have defense-in-depth against them being
mutated. This eliminates the need to `default: lazy{ {} }`
things like Hashes or Arrays.
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'spec')
-rw-r--r-- | spec/unit/mixin/params_validate_spec.rb | 7 | ||||
-rw-r--r-- | spec/unit/property_spec.rb | 45 |
2 files changed, 27 insertions, 25 deletions
diff --git a/spec/unit/mixin/params_validate_spec.rb b/spec/unit/mixin/params_validate_spec.rb index 459c2ce237..1b00d9ee09 100644 --- a/spec/unit/mixin/params_validate_spec.rb +++ b/spec/unit/mixin/params_validate_spec.rb @@ -359,10 +359,11 @@ describe Chef::Mixin::ParamsValidate do expect(@vo.set_or_return(:test, nil, {}).object_id).to eq(value.object_id) end - it "should set and return a default value when the argument is nil, then return the same value" do + it "should set and return a default value when the argument is nil, then return a dup of the value" do value = "meow" - expect(@vo.set_or_return(:test, nil, { default: value }).object_id).to eq(value.object_id) - expect(@vo.set_or_return(:test, nil, {}).object_id).to eq(value.object_id) + expect(@vo.set_or_return(:test, nil, { default: value }).object_id).not_to eq(value.object_id) + expect(@vo.set_or_return(:test, nil, {}).object_id).not_to eq(value.object_id) + expect(@vo.set_or_return(:test, nil, {})).to eql(value) end it "should raise an ArgumentError when argument is nil and required is true" do diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb index 6c64a961b4..aa75710ffb 100644 --- a/spec/unit/property_spec.rb +++ b/spec/unit/property_spec.rb @@ -541,13 +541,16 @@ describe "Chef::Resource.property" do it "when x is not set, it returns ''" do expect(resource.x).to eq "" end - it "x is immutable" do - expect { resource.x << "foo" }.to raise_error(FrozenError, /can't modify frozen String/) + it "setting x does not mutate the default" do + expect(resource.x).to eq "" + resource.x << "foo" + expect(resource.x).to eq "foo" + expect(resource_class.new("other").x).to eq "" end end with_property ":x, default: lazy { '' }" do - it "x is immutable" do + it "setting x does not mutate the default" do expect(resource.x).to eq "" resource.x << "foo" expect(resource.x).to eq "foo" @@ -561,16 +564,14 @@ describe "Chef::Resource.property" do it "when x is not set, it returns {}" do expect(resource.x).to eq({}) end - it "x is immutable" do - expect { resource.x["foo"] = "bar" }.to raise_error(FrozenError, /can't modify frozen Hash/) - end - it "The same exact value is returned multiple times in a row" do - value = resource.x - expect(value).to eq({}) - expect(resource.x.object_id).to eq(value.object_id) + it "setting x does not mutate the default" do + expect(resource.x).to eq({}) + resource.x["plants"] = "zombies" + expect(resource.x).to eq({ "plants" => "zombies" }) + expect(resource_class.new("other").x).to eq({}) end - it "Multiple instances of x receive the exact same value" do - expect(resource.x.object_id).to eq(resource_class.new("blah2").x.object_id) + it "Multiple instances of x receive different values" do + expect(resource.x.object_id).not_to eq(resource_class.new("blah2").x.object_id) end end @@ -594,14 +595,14 @@ describe "Chef::Resource.property" do it "when x is not set, it returns [{foo: 'bar'}]" do expect(resource.x).to eq([{ foo: "bar" }]) end - it "x is immutable" do - expect { resource.x << :other }.to raise_error(FrozenError, /can't modify frozen Array/) - end - it "x.first is immutable" do - expect { resource.x.first[:foo] = "other" }.to raise_error(FrozenError, /can't modify frozen Hash/) + it "setting x does not mutate the default" do + expect(resource.x).to eq([{ foo: "bar" }]) + resource.x[0][:foo] << "baz" + expect(resource.x).to eq([{ foo: "barbaz" }]) + expect(resource_class.new("other").x).to eq([{ foo: "bar" }]) end - it "x.first[:foo] is immutable" do - expect { resource.x.first[:foo] << "other" }.to raise_error(FrozenError, /can't modify frozen String/) + it "Multiple instances of x receive different values" do + expect(resource.x.object_id).not_to eq(resource_class.new("blah2").x.object_id) end end end @@ -708,10 +709,10 @@ 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 each time" do + it "when x is retrieved, coercion is run exactly once" do expect(resource.x).to eq "101" - expect(resource.x).to eq "102" - expect(Namer.current_index).to eq 2 + expect(resource.x).to eq "101" + expect(Namer.current_index).to eq 1 end end |