summaryrefslogtreecommitdiff
path: root/spec/ruby/core/hash/merge_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/hash/merge_spec.rb')
-rw-r--r--spec/ruby/core/hash/merge_spec.rb123
1 files changed, 123 insertions, 0 deletions
diff --git a/spec/ruby/core/hash/merge_spec.rb b/spec/ruby/core/hash/merge_spec.rb
new file mode 100644
index 0000000000..9e566fcee9
--- /dev/null
+++ b/spec/ruby/core/hash/merge_spec.rb
@@ -0,0 +1,123 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Hash#merge" do
+ it "returns a new hash by combining self with the contents of other" do
+ h = { 1 => :a, 2 => :b, 3 => :c }.merge(a: 1, c: 2)
+ h.should == { c: 2, 1 => :a, 2 => :b, a: 1, 3 => :c }
+
+ hash = { a: 1, b: 2 }
+ {}.merge(hash).should == hash
+ hash.merge({}).should == hash
+
+ h = { 1 => :a, 2 => :b, 3 => :c }.merge(1 => :b)
+ h.should == { 1 => :b, 2 => :b, 3 => :c }
+
+ h = { 1 => :a, 2 => :b }.merge(1 => :b, 3 => :c)
+ h.should == { 1 => :b, 2 => :b, 3 => :c }
+ end
+
+ it "sets any duplicate key to the value of block if passed a block" do
+ h1 = { a: 2, b: 1, d: 5 }
+ h2 = { a: -2, b: 4, c: -3 }
+ r = h1.merge(h2) { |k,x,y| nil }
+ r.should == { a: nil, b: nil, c: -3, d: 5 }
+
+ r = h1.merge(h2) { |k,x,y| "#{k}:#{x+2*y}" }
+ r.should == { a: "a:-2", b: "b:9", c: -3, d: 5 }
+
+ -> {
+ h1.merge(h2) { |k, x, y| raise(IndexError) }
+ }.should.raise(IndexError)
+
+ r = h1.merge(h1) { |k,x,y| :x }
+ r.should == { a: :x, b: :x, d: :x }
+ end
+
+ it "tries to convert the passed argument to a hash using #to_hash" do
+ obj = mock('{1=>2}')
+ obj.should_receive(:to_hash).and_return({ 1 => 2 })
+ { 3 => 4 }.merge(obj).should == { 1 => 2, 3 => 4 }
+ end
+
+ it "does not call to_hash on hash subclasses" do
+ { 3 => 4 }.merge(HashSpecs::ToHashHash[1 => 2]).should == { 1 => 2, 3 => 4 }
+ end
+
+ it "returns subclass instance for subclasses" do
+ HashSpecs::MyHash[1 => 2, 3 => 4].merge({ 1 => 2 }).should.instance_of?(HashSpecs::MyHash)
+ HashSpecs::MyHash[].merge({ 1 => 2 }).should.instance_of?(HashSpecs::MyHash)
+
+ { 1 => 2, 3 => 4 }.merge(HashSpecs::MyHash[1 => 2]).class.should == Hash
+ {}.merge(HashSpecs::MyHash[1 => 2]).class.should == Hash
+ end
+
+ it "processes entries with same order as each()" do
+ h = { 1 => 2, 3 => 4, 5 => 6, "x" => nil, nil => 5, [] => [] }
+ merge_pairs = []
+ each_pairs = []
+ h.each_pair { |k, v| each_pairs << [k, v] }
+ h.merge(h) { |k, v1, v2| merge_pairs << [k, v1] }
+ merge_pairs.should == each_pairs
+ end
+
+ it "preserves the order of merged elements" do
+ h1 = { 1 => 2, 3 => 4, 5 => 6 }
+ h2 = { 1 => 7 }
+ merge_pairs = []
+ h1.merge(h2).each_pair { |k, v| merge_pairs << [k, v] }
+ merge_pairs.should == [[1,7], [3, 4], [5, 6]]
+ end
+
+ it "preserves the order of merged elements for large hashes" do
+ h1 = {}
+ h2 = {}
+ merge_pairs = []
+ expected_pairs = []
+ (1..100).each { |x| h1[x] = x; h2[101 - x] = x; expected_pairs << [x, 101 - x] }
+ h1.merge(h2).each_pair { |k, v| merge_pairs << [k, v] }
+ merge_pairs.should == expected_pairs
+ end
+
+ it "accepts multiple hashes" do
+ result = { a: 1 }.merge({ b: 2 }, { c: 3 }, { d: 4 })
+ result.should == { a: 1, b: 2, c: 3, d: 4 }
+ end
+
+ it "accepts zero arguments and returns a copy of self" do
+ hash = { a: 1 }
+ merged = hash.merge
+
+ merged.should.eql?(hash)
+ merged.should_not.equal?(hash)
+ end
+
+ it "retains the default value" do
+ h = Hash.new(1)
+ h.merge(b: 1, d: 2).default.should == 1
+ end
+
+ it "retains the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.merge(b: 1, d: 2).default_proc.should == pr
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.merge(b: 1, d: 2)
+ h2.compare_by_identity?.should == true
+ end
+
+ it "ignores compare_by_identity flag of an argument" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = { b: 1, d: 2 }.merge(h)
+ h2.compare_by_identity?.should == false
+ end
+end
+
+describe "Hash#merge!" do
+ it "is an alias of Hash#update" do
+ Hash.instance_method(:merge!).should == Hash.instance_method(:update)
+ end
+end