summaryrefslogtreecommitdiff
path: root/spec/unit/node
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2016-06-30 09:04:09 -0700
committerGitHub <noreply@github.com>2016-06-30 09:04:09 -0700
commitd463412ce622479465279b0c5613ad7926664f93 (patch)
tree7e44f4042e11c45dad97f6b4695d375f1ddf948e /spec/unit/node
parentc3c728b56d72986f9d02f8a6396935d089323a00 (diff)
parent86fa507226b484a71a45ef6129840bc3928be6b7 (diff)
downloadchef-d463412ce622479465279b0c5613ad7926664f93.tar.gz
Merge pull request #5029 from chef/lcg/attributes-v1.1
Attributes v1.1
Diffstat (limited to 'spec/unit/node')
-rw-r--r--spec/unit/node/attribute_spec.rb16
-rw-r--r--spec/unit/node/immutable_collections_spec.rb4
-rw-r--r--spec/unit/node/vivid_mash_spec.rb344
3 files changed, 355 insertions, 9 deletions
diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb
index 57ad3c0c25..e40f454c0b 100644
--- a/spec/unit/node/attribute_spec.rb
+++ b/spec/unit/node/attribute_spec.rb
@@ -218,7 +218,7 @@ describe Chef::Node::Attribute do
end
it "gives the value at each level of precedence for a path spec" do
- expected = [["set_unless_enabled?", false],
+ expected = [
%w{default default},
%w{env_default env_default},
%w{role_default role_default},
@@ -417,12 +417,6 @@ describe Chef::Node::Attribute do
expect(@attributes.normal["foo"]["bar"]).to eq(:baz)
end
- it "should optionally skip setting the value if one already exists" do
- @attributes.set_unless_value_present = true
- @attributes.normal["hostname"] = "bar"
- expect(@attributes["hostname"]).to eq("latte")
- end
-
it "does not support ||= when setting" do
# This is a limitation of auto-vivification.
# Users who need this behavior can use set_unless and friends
@@ -493,6 +487,7 @@ describe Chef::Node::Attribute do
end
it "should return true if an attribute exists but is set to nil using dot notation" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(@attributes.music.deeper.has_key?("gates_of_ishtar")).to eq(true)
end
@@ -533,10 +528,12 @@ describe Chef::Node::Attribute do
describe "method_missing" do
it "should behave like a [] lookup" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(@attributes.music.mastodon).to eq("rocks")
end
it "should allow the last method to set a value if it has an = sign on the end" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
@attributes.normal.music.mastodon = %w{dream still shining}
expect(@attributes.normal.music.mastodon).to eq(%w{dream still shining})
end
@@ -577,7 +574,7 @@ describe Chef::Node::Attribute do
it "should yield lower if we go deeper" do
collect = Array.new
- @attributes.one.keys.each do |k|
+ @attributes["one"].keys.each do |k|
collect << k
end
expect(collect.include?("two")).to eq(true)
@@ -587,7 +584,7 @@ describe Chef::Node::Attribute do
end
it "should not raise an exception if one of the hashes has a nil value on a deep lookup" do
- expect { @attributes.place.keys { |k| } }.not_to raise_error
+ expect { @attributes["place"].keys { |k| } }.not_to raise_error
end
end
@@ -1171,6 +1168,7 @@ describe Chef::Node::Attribute do
end
it "raises an error when using `attr=value`" do
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect { @attributes.new_key = "new value" }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
end
diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb
index f57ed459cd..fe4e50d1bd 100644
--- a/spec/unit/node/immutable_collections_spec.rb
+++ b/spec/unit/node/immutable_collections_spec.rb
@@ -95,6 +95,10 @@ describe Chef::Node::ImmutableMash do
:replace,
:select!,
:shift,
+ :write,
+ :write!,
+ :unlink,
+ :unlink!,
].each do |mutator|
it "doesn't allow mutation via `#{mutator}'" do
expect { @immutable_mash.send(mutator) }.to raise_error(Chef::Exceptions::ImmutableAttributeModification)
diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb
new file mode 100644
index 0000000000..ca5eddce57
--- /dev/null
+++ b/spec/unit/node/vivid_mash_spec.rb
@@ -0,0 +1,344 @@
+#
+# Copyright:: Copyright 2016, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+require "chef/node/attribute_collections"
+
+describe Chef::Node::VividMash do
+ class Root
+ attr_accessor :top_level_breadcrumb
+ end
+
+ let(:root) { Root.new }
+
+ let(:vivid) do
+ expect(root).to receive(:reset_cache).at_least(:once).with(nil)
+ Chef::Node::VividMash.new(root,
+ { "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil }
+ )
+ end
+
+ context "#read" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "reads hashes deeply" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.read("one", "two", "three")).to eql("four")
+ end
+
+ it "does not trainwreck when hitting hash keys that do not exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.read("one", "five", "six")).to eql(nil)
+ end
+
+ it "does not trainwreck when hitting an array with an out of bounds index" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect(vivid.read("array", 5, "one")).to eql(nil)
+ end
+
+ it "does not trainwreck when hitting an array with a string key" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect(vivid.read("array", "one", "two")).to eql(nil)
+ end
+
+ it "does not trainwreck when traversing a nil" do
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
+ expect(vivid.read("nil", "one", "two")).to eql(nil)
+ end
+ end
+
+ context "#exist?" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "true if there's a hash key there" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.exist?("one", "two", "three")).to be true
+ end
+
+ it "true for intermediate hashes" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.exist?("one")).to be true
+ end
+
+ it "true for arrays that exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect(vivid.exist?("array", 1)).to be true
+ end
+
+ it "true when the value of the key is nil" do
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
+ expect(vivid.exist?("nil")).to be true
+ end
+
+ it "false when attributes don't exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.exist?("one", "five", "six")).to be false
+ end
+
+ it "false when traversing a non-container" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.exist?("one", "two", "three", "four")).to be false
+ end
+
+ it "false when an array index does not exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect(vivid.exist?("array", 3)).to be false
+ end
+
+ it "false when traversing a nil" do
+ expect(root).to receive(:top_level_breadcrumb=).with("nil").and_call_original
+ expect(vivid.exist?("nil", "foo", "bar")).to be false
+ end
+ end
+
+ context "#read!" do
+ before do
+ # vivify the vividmash, then we're read-only so the cache should never be cleared afterwards
+ vivid
+ expect(root).not_to receive(:reset_cache)
+ end
+
+ it "reads hashes deeply" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect(vivid.read!("one", "two", "three")).to eql("four")
+ end
+
+ it "reads arrays deeply" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect(vivid.read!("array", 1)).to eql(1)
+ end
+
+ it "throws an exception when attributes do not exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect { vivid.read!("one", "five", "six") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+
+ it "throws an exception when traversing a non-container" do
+ expect(root).to receive(:top_level_breadcrumb=).with("one").and_call_original
+ expect { vivid.read!("one", "two", "three", "four") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+
+ it "throws an exception when an array element does not exist" do
+ expect(root).to receive(:top_level_breadcrumb=).with("array").and_call_original
+ expect { vivid.read!("array", 3) }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ end
+ end
+
+ context "#write" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should write into hashes" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five", "six")
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+
+ it "should deeply autovivify" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
+ end
+
+ it "should raise an exception if you overwrite an array with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ vivid.write("array", "five", "six")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => "six" }, "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through an array with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ vivid.write("array", "five", "six", "seven")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => { "six" => "seven" } }, "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a string with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "two", "three", "four", "five")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => "five" } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a string with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "two", "three", "four", "five", "six")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => { "five" => "six" } } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a nil with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ vivid.write("nil", "one", "two")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => "two" } })
+ end
+
+ it "should raise an exception if you traverse through a nil with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ vivid.write("nil", "one", "two", "three")
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => { "two" => "three" } } })
+ end
+
+ it "writes with a block" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write("one", "five") { "six" }
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+ end
+
+ context "#write!" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should write into hashes" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five", "six")
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+
+ it "should deeply autovivify" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
+ expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
+ end
+
+ it "should raise an exception if you overwrite an array with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("array", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through an array with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("array", "five", "six", "seven") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a string with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("one", "two", "three", "four", "five") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a string with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("one", "two", "three", "four", "five", "six") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you overwrite a nil with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("nil", "one", "two") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should raise an exception if you traverse through a nil with a hash" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.write!("nil", "one", "two", "three") }.to raise_error(Chef::Exceptions::AttributeTypeMismatch)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "writes with a block" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ vivid.write!("one", "five") { "six" }
+ expect(vivid["one"]["five"]).to eql("six")
+ end
+ end
+
+ context "#unlink" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should return nil if the keys already don't exist" do
+ expect(root).not_to receive(:reset_cache)
+ expect(vivid.unlink("five", "six", "seven", "eight")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink hashes" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink array elements" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ expect(vivid.unlink("array", 2)).to eql(2)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
+ end
+
+ it "should unlink nil" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(vivid.unlink("nil")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
+ end
+
+ it "should traverse a nil and safely do nothing" do
+ expect(root).not_to receive(:reset_cache)
+ expect(vivid.unlink("nil", "foo")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+ end
+
+ context "#unlink!" do
+ before do
+ vivid
+ expect(root).not_to receive(:reset_cache).with(nil)
+ end
+
+ it "should raise an exception if the keys already don't exist" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.unlink!("five", "six", "seven", "eight") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink! hashes" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
+ expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+
+ it "should unlink! array elements" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ expect(vivid.unlink!("array", 2)).to eql(2)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1 ], "nil" => nil })
+ end
+
+ it "should unlink! nil" do
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(vivid.unlink!("nil")).to eql(nil)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
+ end
+
+ it "should raise an exception if it traverses a nil" do
+ expect(root).not_to receive(:reset_cache)
+ expect { vivid.unlink!("nil", "foo") }.to raise_error(Chef::Exceptions::NoSuchAttribute)
+ expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => nil })
+ end
+ end
+end