Skip to content

Commit

Permalink
Merge pull request #2037 from abscondment/fix-2036-ruby-hash
Browse files Browse the repository at this point in the history
Fix #2036 (Ruby `hash` broken for Messages with repeated fields.)
  • Loading branch information
haberman authored Sep 19, 2016
2 parents c44ca26 + de02863 commit b5bbdb0
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 8 deletions.
12 changes: 5 additions & 7 deletions ruby/ext/google/protobuf_c/repeated_field.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,22 +447,20 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
*/
VALUE RepeatedField_hash(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);

VALUE hash = LL2NUM(0);

st_index_t h = rb_hash_start(0);
VALUE hash_sym = rb_intern("hash");
upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class;
size_t elem_size = native_slot_size(field_type);
size_t off = 0;
for (int i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, field_type_class, mem);
hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
hash = rb_funcall(hash, rb_intern("^"), 1,
rb_funcall(elem, rb_intern("hash"), 0));
h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
}
h = rb_hash_end(h);

return hash;
return INT2FIX(h);
}

/*
Expand Down
5 changes: 4 additions & 1 deletion ruby/tests/basic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,15 @@ def test_inspect

def test_hash
m1 = TestMessage.new(:optional_int32 => 42)
m2 = TestMessage.new(:optional_int32 => 102)
m2 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
m3 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
assert m1.hash != 0
assert m2.hash != 0
assert m3.hash != 0
# relying on the randomness here -- if hash function changes and we are
# unlucky enough to get a collision, then change the values above.
assert m1.hash != m2.hash
assert_equal m2.hash, m3.hash
end

def test_unknown_field_errors
Expand Down

0 comments on commit b5bbdb0

Please sign in to comment.