summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-02-25 13:22:43 -0800
committerLamont Granquist <lamont@scriptkiddie.org>2016-02-25 13:22:43 -0800
commita67b300a91114855381a2cf8353db94de6d280aa (patch)
treefd8476c423ed33b97f3d7fc621ab1c563be9452c
parent25dadec4243bdf87c65b5e8c1dbf21d1df5c27a7 (diff)
downloadchef-a67b300a91114855381a2cf8353db94de6d280aa.tar.gz
fixing more copy-on-write bugs
getting trolled by `@foo =` vs. `foo =` plus the indirection in handling `#ffi-yajl` was really odd. added pending test for `dup` returning a decorated object because it feels like it should rather than like it is now where it does not.
-rw-r--r--lib/chef/node/attribute_trait/copy_on_write.rb2
-rw-r--r--lib/chef/node/attribute_trait/decorator.rb10
-rw-r--r--spec/unit/node/attribute_trait/decorator_spec.rb23
-rw-r--r--spec/unit/node/cow_mash_spec.rb11
4 files changed, 37 insertions, 9 deletions
diff --git a/lib/chef/node/attribute_trait/copy_on_write.rb b/lib/chef/node/attribute_trait/copy_on_write.rb
index b8ed73a340..fb0c3b86ee 100644
--- a/lib/chef/node/attribute_trait/copy_on_write.rb
+++ b/lib/chef/node/attribute_trait/copy_on_write.rb
@@ -36,7 +36,7 @@ class Chef
MUTATOR_METHODS.each do |method|
define_method method do |*args, &block|
- wrapped_object = safe_dup(wrapped_object)
+ @wrapped_object = dup
super(*args, &block)
end
end
diff --git a/lib/chef/node/attribute_trait/decorator.rb b/lib/chef/node/attribute_trait/decorator.rb
index 59d71febfa..888d404bf4 100644
--- a/lib/chef/node/attribute_trait/decorator.rb
+++ b/lib/chef/node/attribute_trait/decorator.rb
@@ -44,7 +44,7 @@ class Chef
#
def ffi_yajl(*opts)
- for_json.ffi_yajl(*opts)
+ wrapped_object.ffi_yajl(*opts)
end
def to_json(*opts)
@@ -52,13 +52,7 @@ class Chef
end
def for_json
- if is_a?(Hash)
- to_hash
- elsif is_a?(Array)
- to_ary
- else
- wrapped_object
- end
+ wrapped_object
end
#
diff --git a/spec/unit/node/attribute_trait/decorator_spec.rb b/spec/unit/node/attribute_trait/decorator_spec.rb
index 3e261f28b5..f024dce4c1 100644
--- a/spec/unit/node/attribute_trait/decorator_spec.rb
+++ b/spec/unit/node/attribute_trait/decorator_spec.rb
@@ -77,6 +77,29 @@ describe Chef::Node::AttributeTrait::Decorator do
test.each { |k, v| expect(v).not_to be_instance_of(Test) }
end
end
+
+ context "Hash#dup" do
+ it "yields decorated objects" do
+ pending "not fixed yet"
+ test["foo"] = { "bar" => "baz" }
+ test["bar"] = [ 1, 2 ]
+ testdup = test.dup
+ expect(testdup).to be_instance_of(Test)
+ expect(testdup["foo"]).to be_instance_of(Test)
+ expect(testdup["bar"]).to be_instance_of(Test)
+ end
+
+ it "deep dups the wrapped_object" do
+ test["foo"] = { "bar" => "baz" }
+ test["bar"] = [ 1, 2 ]
+ testdup = test.dup
+ testdup["foo"]["qux"] = "quux"
+ testdup["foo"]["bar"] << "buzz"
+ testdup["bar"] << 3
+ testdup["baz"] = false
+ expect(test).to eql({"foo" => { "bar" => "baz" }, "bar" => [ 1, 2 ]})
+ end
+ end
end
context "as an Array" do
diff --git a/spec/unit/node/cow_mash_spec.rb b/spec/unit/node/cow_mash_spec.rb
index cda31089fa..135d21341a 100644
--- a/spec/unit/node/cow_mash_spec.rb
+++ b/spec/unit/node/cow_mash_spec.rb
@@ -7,6 +7,7 @@ describe Chef::Node::COWMash do
it "behaves correctly" do
hash = { "foo" => true, "bar" => false }
cow = Chef::Node::COWMash.new(wrapped_object: hash)
+ expect(hash).not_to receive(:keep_if)
expect(cow.keep_if { |k, v| v }).to eql({ "foo" => true })
expect(hash).to eql({ "foo" => true, "bar" => false })
expect(cow).to eql({ "foo" => true })
@@ -19,4 +20,14 @@ describe Chef::Node::COWMash do
expect(cow.keep_if { |k, v| v }).to equal(cow)
end
end
+
+ context "#[]=" do
+ it "behaves correctly" do
+ hash = { "foo" => true, "bar" => false }
+ cow = Chef::Node::COWMash.new(wrapped_object: hash)
+ expect(cow["baz"] = "qux").to eql("qux")
+ expect(cow).to eql({ "foo" => true, "bar" => false, "baz" => "qux" })
+ expect(hash).to eql({ "foo" => true, "bar" => false })
+ end
+ end
end