summaryrefslogtreecommitdiff
path: root/spec/rubyspec/core/hash/shared/equal.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/rubyspec/core/hash/shared/equal.rb')
-rw-r--r--spec/rubyspec/core/hash/shared/equal.rb90
1 files changed, 90 insertions, 0 deletions
diff --git a/spec/rubyspec/core/hash/shared/equal.rb b/spec/rubyspec/core/hash/shared/equal.rb
new file mode 100644
index 0000000000..43606437fe
--- /dev/null
+++ b/spec/rubyspec/core/hash/shared/equal.rb
@@ -0,0 +1,90 @@
+describe :hash_equal, shared: true do
+ it "does not compare values when keys don't match" do
+ value = mock('x')
+ value.should_not_receive(:==)
+ value.should_not_receive(:eql?)
+ { 1 => value }.send(@method, { 2 => value }).should be_false
+ end
+
+ it "returns false when the numbers of keys differ without comparing any elements" do
+ obj = mock('x')
+ h = { obj => obj }
+
+ obj.should_not_receive(:==)
+ obj.should_not_receive(:eql?)
+
+ {}.send(@method, h).should be_false
+ h.send(@method, {}).should be_false
+ end
+
+ it "first compares keys via hash" do
+ x = mock('x')
+ x.should_receive(:hash).and_return(0)
+ y = mock('y')
+ y.should_receive(:hash).and_return(0)
+
+ { x => 1 }.send(@method, { y => 1 }).should be_false
+ end
+
+ it "does not compare keys with different hash codes via eql?" do
+ x = mock('x')
+ y = mock('y')
+ x.should_not_receive(:eql?)
+ y.should_not_receive(:eql?)
+
+ x.should_receive(:hash).and_return(0)
+ y.should_receive(:hash).and_return(1)
+
+ def x.hash() 0 end
+ def y.hash() 1 end
+
+ { x => 1 }.send(@method, { y => 1 }).should be_false
+ end
+
+ it "computes equality for recursive hashes" do
+ h = {}
+ h[:a] = h
+ h.send(@method, h[:a]).should be_true
+ (h == h[:a]).should be_true
+ end
+
+ it "computes equality for complex recursive hashes" do
+ a, b = {}, {}
+ a.merge! self: a, other: b
+ b.merge! self: b, other: a
+ a.send(@method, b).should be_true # they both have the same structure!
+
+ c = {}
+ c.merge! other: c, self: c
+ c.send(@method, a).should be_true # subtle, but they both have the same structure!
+ a[:delta] = c[:delta] = a
+ c.send(@method, a).should be_false # not quite the same structure, as a[:other][:delta] = nil
+ c[:delta] = 42
+ c.send(@method, a).should be_false
+ a[:delta] = 42
+ c.send(@method, a).should be_false
+ b[:delta] = 42
+ c.send(@method, a).should be_true
+ end
+
+ it "computes equality for recursive hashes & arrays" do
+ x, y, z = [], [], []
+ a, b, c = {foo: x, bar: 42}, {foo: y, bar: 42}, {foo: z, bar: 42}
+ x << a
+ y << c
+ z << b
+ b.send(@method, c).should be_true # they clearly have the same structure!
+ y.send(@method, z).should be_true
+ a.send(@method, b).should be_true # subtle, but they both have the same structure!
+ x.send(@method, y).should be_true
+ y << x
+ y.send(@method, z).should be_false
+ z << x
+ y.send(@method, z).should be_true
+
+ a[:foo], a[:bar] = a[:bar], a[:foo]
+ a.send(@method, b).should be_false
+ b[:bar] = b[:foo]
+ b.send(@method, c).should be_false
+ end
+end