Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add and fix specs for Hash keys with private hash method #2170

Merged
merged 2 commits into from

2 participants

Ravil Bayramgalin Dirkjan Bussink
Ravil Bayramgalin

MRI and JRuby have support for Hash keys with private hash method. Rubinius currently throws an exception.

I've encountered this error when running specs on travis – https://travis-ci.org/brainopia/cassandra-mapper

This pull-request fixes it.

Dirkjan Bussink
Owner

There's one problem with this pull request, that is that send() currently is significantly slower than a regular call, so merging this would affect Hash performance everywhere.

We probably have to use the Rubinius.privately construct we use in other places to allow private sends.

Ravil Bayramgalin

Thanks, I've changed it to use Rubinius.privately

spec/ruby/core/hash/element_reference_spec.rb
@@ -112,4 +112,9 @@
new_hash(x => :x)[x].should == :x
end
+
+ it "supports keys with private #hash method" do
+ k = Class.new { private :hash }.new
+ lambda { new_hash[k] }.should_not raise_error
Dirkjan Bussink Owner

We should have better specs for this, we should assert on the actual behavior, not on whether it doesn't raise an error. Not raising an error would be a valid spec for any code, so we should verify that the lookup actually works here. Having an implementation for example that ignores values with private hashes here would be valid according to this spec.

The best idea is probably to add a class for testing this in spec/ruby/core/hash/fixtures/classes.rb and use that to verify the behavior. In this case you'd want to specify that it retrieves the correct value from a hash.

Same comment applies to the spec for []= btw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Ravil Bayramgalin

Done :)

Dirkjan Bussink dbussink merged commit abc1bc5 into from
Dirkjan Bussink
Owner

Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
7 kernel/common/hash18.rb
View
@@ -67,7 +67,7 @@ def []=(key, value)
redistribute @entries if @size > @max_entries
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
index = key_hash & @mask
item = @entries[index]
@@ -116,8 +116,7 @@ def default_proc
def delete(key)
Rubinius.check_frozen
-
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
ents = @entries
@@ -201,7 +200,7 @@ def fetch(key, default=undefined)
# Searches for an item matching +key+. Returns the item
# if found. Otherwise returns +nil+.
def find_item(key)
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
item = @entries[key_index(key_hash)]
while item
7 kernel/common/hash19.rb
View
@@ -122,7 +122,7 @@ def []=(key, value)
redistribute @entries if @size > @max_entries
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
index = key_hash & @mask
item = @entries[index]
@@ -198,8 +198,7 @@ def default_proc=(prc)
def delete(key)
Rubinius.check_frozen
-
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
index = key_index key_hash
if item = @entries[index]
@@ -262,7 +261,7 @@ def fetch(key, default=undefined)
# Searches for an item matching +key+. Returns the item
# if found. Otherwise returns +nil+.
def find_item(key)
- key_hash = key.hash
+ key_hash = Rubinius.privately { key.hash }
item = @entries[key_index(key_hash)]
while item
5 spec/ruby/core/hash/delete_spec.rb
View
@@ -20,6 +20,11 @@
new_hash { :defualt }.delete(:d).should == nil
end
+ it "accepts keys with private #hash method" do
+ key = HashSpecs::KeyWithPrivateHash.new
+ new_hash(key => 5).delete(key).should == 5
+ end
+
ruby_version_is "" ... "1.9" do
it "raises a TypeError if called on a frozen instance" do
lambda { HashSpecs.frozen_hash.delete("foo") }.should raise_error(TypeError)
5 spec/ruby/core/hash/element_reference_spec.rb
View
@@ -112,4 +112,9 @@
new_hash(x => :x)[x].should == :x
end
+
+ it "supports keys with private #hash method" do
+ key = HashSpecs::KeyWithPrivateHash.new
+ new_hash(key => 42)[key].should == 42
+ end
end
4 spec/ruby/core/hash/fixtures/classes.rb
View
@@ -29,6 +29,10 @@ def to_hash
end
end
+ class KeyWithPrivateHash
+ private :hash
+ end
+
def self.empty_frozen_hash
@empty ||= new_hash
@empty.freeze
7 spec/ruby/core/hash/shared/store.rb
View
@@ -27,6 +27,13 @@ def key.reverse() "bar" end
h.size.should == 2
end
+ it "accepts keys with private #hash method" do
+ key = HashSpecs::KeyWithPrivateHash.new
+ h = new_hash
+ h[key] = "foo"
+ h[key].should == "foo"
+ end
+
it "duplicates and freezes string keys" do
key = "foo"
h = new_hash
Something went wrong with that request. Please try again.