summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-09-28 10:10:18 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2016-10-25 09:29:29 -0700
commit70336a154e62816fb11f09885ad93e67f001af0e (patch)
treee811051b02e5ca5f2676fe5f5384aaadfe361404
parent6859b99ca4b79077c99ddeadc91333ce86b40454 (diff)
downloadchef-70336a154e62816fb11f09885ad93e67f001af0e.tar.gz
add specs
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--spec/unit/node_spec.rb84
1 files changed, 84 insertions, 0 deletions
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index a78ad2c076..3b9501d73c 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -1709,4 +1709,88 @@ describe Chef::Node do
end
end
+ describe "path tracking via __path" do
+ it "works through hash keys" do
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ expect(node["foo"]["bar"].__path).to eql(%w{foo bar})
+ end
+
+ it "works through the default level" do
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ expect(node.default["foo"]["bar"].__path).to eql(%w{foo bar})
+ end
+
+ it "works through arrays" do
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
+ expect(node["foo"][0].__path).to eql(["foo", 0])
+ expect(node["foo"][0]["bar"].__path).to eql(["foo", 0, "bar"])
+ end
+
+ it "works through arrays at the default level" do
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
+ expect(node.default["foo"][0].__path).to eql(["foo", 0])
+ expect(node.default["foo"][0]["bar"].__path).to eql(["foo", 0, "bar"])
+ end
+
+ # if we set __path in the initializer we'd get this wrong, this is why we
+ # update the path on every #[] or #[]= operator
+ it "works on access when the node has been rearranged" do
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ a = node.default["foo"]
+ node.default["fizz"] = a
+ expect(node["fizz"]["bar"].__path).to eql(%w{fizz bar})
+ expect(node["foo"]["bar"].__path).to eql(%w{foo bar})
+ end
+
+ # We have a problem because the __path is stored on in each node, but the
+ # node can be wired up at multiple locations in the tree via pointers. One
+ # solution would be to deep-dup the value in `#[]=(key, value)` and fix the
+ # __path on all the dup'd nodes. The problem is that this would create an
+ # unusual situation where after assignment, you couldn't mutate the thing you
+ # hand a handle on. I'm not entirely positive this behavior is the correct
+ # thing to support, but it is more hash-like (although if we start with a hash
+ # then convert_value does its thing and we *do* get dup'd on assignment). This
+ # behavior likely makes any implementation of a deep merge cache built over the
+ # top of __path tracking have edge conditions where it will fail.
+ #
+ # Removing this support would be a breaking change. The test is included here
+ # because it seems most likely that someone would break this behavior while trying
+ # to fix __path behavior.
+ it "does not dup in the background when a node is assigned" do
+ # get a handle on a vividmash (can't be a hash or else we convert_value it)
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ a = node.default["foo"]
+ # assign that somewhere else in the tree
+ node.default["fizz"] = a
+ # now upate the source
+ a["duptest"] = true
+ # the tree should have been updated
+ expect(node.default["fizz"]["duptest"]).to be true
+ expect(node["fizz"]["duptest"]).to be true
+ end
+ end
+
+ describe "root tracking via __root" do
+ it "works through hash keys" do
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ expect(node["foo"]["bar"].__root).to eql(node.attributes)
+ end
+
+ it "works through the default level" do
+ node.default["foo"] = { "bar" => { "baz" => "qux" } }
+ expect(node.default["foo"]["bar"].__root).to eql(node.attributes)
+ end
+
+ it "works through arrays" do
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
+ expect(node["foo"][0].__root).to eql(node.attributes)
+ expect(node["foo"][0]["bar"].__root).to eql(node.attributes)
+ end
+
+ it "works through arrays at the default level" do
+ node.default["foo"] = [ { "bar" => { "baz" => "qux" } } ]
+ expect(node.default["foo"][0].__root).to eql(node.attributes)
+ expect(node.default["foo"][0]["bar"].__root).to eql(node.attributes)
+ end
+ end
end