1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Hash#[]" do
it "returns the value for key" do
obj = mock('x')
h = { 1 => 2, 3 => 4, "foo" => "bar", obj => obj, [] => "baz" }
h[1].should == 2
h[3].should == 4
h["foo"].should == "bar"
h[obj].should == obj
h[[]].should == "baz"
end
it "returns nil as default default value" do
{ 0 => 0 }[5].should == nil
end
it "returns the default (immediate) value for missing keys" do
h = Hash.new(5)
h[:a].should == 5
h[:a] = 0
h[:a].should == 0
h[:b].should == 5
end
it "calls subclass implementations of default" do
h = HashSpecs::DefaultHash.new
h[:nothing].should == 100
end
it "does not create copies of the immediate default value" do
str = "foo"
h = Hash.new(str)
a = h[:a]
b = h[:b]
a << "bar"
a.should equal(b)
a.should == "foobar"
b.should == "foobar"
end
it "returns the default (dynamic) value for missing keys" do
h = Hash.new { |hsh, k| k.kind_of?(Numeric) ? hsh[k] = k + 2 : hsh[k] = k }
h[1].should == 3
h['this'].should == 'this'
h.should == { 1 => 3, 'this' => 'this' }
i = 0
h = Hash.new { |hsh, key| i += 1 }
h[:foo].should == 1
h[:foo].should == 2
h[:bar].should == 3
end
it "does not return default values for keys with nil values" do
h = Hash.new(5)
h[:a] = nil
h[:a].should == nil
h = Hash.new { 5 }
h[:a] = nil
h[:a].should == nil
end
it "compares keys with eql? semantics" do
{ 1.0 => "x" }[1].should == nil
{ 1.0 => "x" }[1.0].should == "x"
{ 1 => "x" }[1.0].should == nil
{ 1 => "x" }[1].should == "x"
end
it "compares key via hash" do
x = mock('0')
x.should_receive(:hash).and_return(0)
h = {}
# 1.9 only calls #hash if the hash had at least one entry beforehand.
h[:foo] = :bar
h[x].should == nil
end
it "does not compare keys with different #hash values via #eql?" do
x = mock('x')
x.should_not_receive(:eql?)
x.stub!(:hash).and_return(0)
y = mock('y')
y.should_not_receive(:eql?)
y.stub!(:hash).and_return(1)
{ y => 1 }[x].should == nil
end
it "compares keys with the same #hash value via #eql?" do
x = mock('x')
x.should_receive(:eql?).and_return(true)
x.stub!(:hash).and_return(42)
y = mock('y')
y.should_not_receive(:eql?)
y.stub!(:hash).and_return(42)
{ y => 1 }[x].should == 1
end
it "finds a value via an identical key even when its #eql? isn't reflexive" do
x = mock('x')
x.should_receive(:hash).at_least(1).and_return(42)
x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
{ x => :x }[x].should == :x
end
it "supports keys with private #hash method" do
key = HashSpecs::KeyWithPrivateHash.new
{ key => 42 }[key].should == 42
end
it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
code = <<-EOC
load '#{fixture __FILE__, "name.rb"}'
hash = { true => 42, false => 42, 1 => 42, 2.0 => 42, "hello" => 42, :ok => 42 }
[true, false, 1, 2.0, "hello", :ok].each do |value|
raise "incorrect value" unless hash[value] == 42
end
puts "Ok."
EOC
result = ruby_exe(code, args: "2>&1")
result.should == "Ok.\n"
end
end
|