atlasdb icon indicating copy to clipboard operation
atlasdb copied to clipboard

RangeRequest Breaches The hashCode() Contract

Open jeremyk-91 opened this issue 4 years ago • 0 comments

    @Test
    public void wat() {
        RangeRequest r1 = RangeRequest.builder()
                .startRowInclusive(PtBytes.toBytes("tom"))
                .endRowExclusive(PtBytes.toBytes("zzzz"))
                .retainColumns(ImmutableList.of(PtBytes.toBytes("name")))
                .build();
        RangeRequest r2 = RangeRequest.builder()
                .startRowInclusive(PtBytes.toBytes("tom"))
                .endRowExclusive(PtBytes.toBytes("zzzz"))
                .retainColumns(ImmutableList.of(PtBytes.toBytes("name")))
                .build();

        assertThat(r1).isEqualTo(r2); // passes
        assertThat(r1.hashCode()).isEqualTo(r2.hashCode()); // :(
        assertThat(ImmutableSet.of(r1, r2).size()).isEqualTo(1); // :(
    }

Ran into this when trying to work on the range requests issue. Looks like this is caused by the way the hash calls Object.hash on an ImmutableSortedSet of byte arrays, among other things - this extracts the hash code of the ImmutableSortedSet, which is based on the hash code of its elements (but of course for arrays these are identity-hashcodes).

This is not a problem for Guava, because they do warn about undefined behaviour for users of arrays with a comparator like unsigned bytes.

Unsure about the scope of the badness, but uses of things like Map<RangeRequest, T> where we expect multiple updates to a key to replace its value / use computeIfAbsent style workflows are broken.

jeremyk-91 avatar Apr 09 '20 17:04 jeremyk-91