• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 
3 package com.google.common.hash;
4 
5 import com.google.common.collect.ImmutableList;
6 
7 import junit.framework.TestCase;
8 
9 import java.util.Arrays;
10 
11 /**
12  * Tests for HashCodes, especially making sure that their endianness promises (big-endian)
13  * are upheld.
14  *
15  * @author andreou@google.com (Dimitris Andreou)
16  */
17 public class HashCodesTest extends TestCase {
18   // note: asInt(), asLong() are in little endian
19   private static final ImmutableList<ExpectedHashCode> expectedHashCodes = ImmutableList.of(
20       new ExpectedHashCode(new byte[] {
21         (byte) 0xef, (byte) 0xcd, (byte) 0xab, (byte) 0x89,
22         (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01},
23         0x89abcdef, 0x0123456789abcdefL, "efcdab8967452301"),
24 
25       new ExpectedHashCode(new byte[] {
26         (byte) 0xef, (byte) 0xcd, (byte) 0xab, (byte) 0x89,
27         (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01, // up to here, same bytes as above
28         (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
29         (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08},
30         0x89abcdef, 0x0123456789abcdefL, // asInt/asLong as above, due to equal eight first bytes
31         "efcdab89674523010102030405060708"),
32 
33       new ExpectedHashCode(new byte[] { (byte) 0xdf, (byte) 0x9b, (byte) 0x57, (byte) 0x13 },
34         0x13579bdf, null, "df9b5713"),
35 
36       new ExpectedHashCode(new byte[] {
37           (byte) 0xcd, (byte) 0xab, (byte) 0x00, (byte) 0x00},
38           0x0000abcd, null, "cdab0000"),
39 
40       new ExpectedHashCode(new byte[] {
41           (byte) 0xef, (byte) 0xcd, (byte) 0xab, (byte) 0x00,
42           (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00},
43           0x00abcdef, 0x0000000000abcdefL, "efcdab0000000000")
44     );
45 
46   // expectedHashCodes must contain at least one hash code with 4 bytes
testFromInt()47   public void testFromInt() {
48     for (ExpectedHashCode expected : expectedHashCodes) {
49       if (expected.bytes.length == 4) {
50         HashCode fromInt = HashCodes.fromInt(expected.asInt);
51         assertExpectedHashCode(expected, fromInt);
52       }
53     }
54   }
55 
56   // expectedHashCodes must contain at least one hash code with 8 bytes
testFromLong()57   public void testFromLong() {
58     for (ExpectedHashCode expected : expectedHashCodes) {
59       if (expected.bytes.length == 8) {
60         HashCode fromLong = HashCodes.fromLong(expected.asLong);
61         assertExpectedHashCode(expected, fromLong);
62       }
63     }
64   }
65 
testFromBytes()66   public void testFromBytes() {
67     for (ExpectedHashCode expected : expectedHashCodes) {
68       HashCode fromBytes = HashCodes.fromBytes(expected.bytes);
69       assertExpectedHashCode(expected, fromBytes);
70     }
71   }
72 
assertExpectedHashCode(ExpectedHashCode expected, HashCode hash)73   private void assertExpectedHashCode(ExpectedHashCode expected, HashCode hash) {
74     assertTrue(Arrays.equals(expected.bytes, hash.asBytes()));
75     byte[] bb = new byte[hash.bits() / 8];
76     hash.writeBytesTo(bb, 0, bb.length);
77     assertTrue(Arrays.equals(expected.bytes, bb));
78     assertEquals(expected.asInt, hash.asInt());
79     if (expected.asLong == null) {
80       try {
81         hash.asLong();
82         fail();
83       } catch (IllegalStateException ok) {}
84     } else {
85       assertEquals(expected.asLong.longValue(), hash.asLong());
86     }
87     assertEquals(expected.toString, hash.toString());
88     assertSideEffectFree(hash);
89     assertReadableBytes(hash);
90   }
91 
assertSideEffectFree(HashCode hash)92   private void assertSideEffectFree(HashCode hash) {
93     byte[] original = hash.asBytes();
94     byte[] mutated = hash.asBytes();
95     mutated[0]++;
96     assertTrue(Arrays.equals(original, hash.asBytes()));
97   }
98 
assertReadableBytes(HashCode hashCode)99   private void assertReadableBytes(HashCode hashCode) {
100     assertTrue(hashCode.bits() >= 32); // sanity
101     byte[] hashBytes = hashCode.asBytes();
102     int totalBytes = hashCode.bits() / 8;
103 
104     for (int bytes = 0; bytes < totalBytes; bytes++) {
105       byte[] bb = new byte[bytes];
106       hashCode.writeBytesTo(bb, 0, bb.length);
107 
108       assertTrue(Arrays.equals(Arrays.copyOf(hashBytes, bytes), bb));
109     }
110   }
111 
112   private static class ExpectedHashCode {
113     final byte[] bytes;
114     final int asInt;
115     final Long asLong; // null means that asLong should throw an exception
116     final String toString;
ExpectedHashCode(byte[] bytes, int asInt, Long asLong, String toString)117     ExpectedHashCode(byte[] bytes, int asInt, Long asLong, String toString) {
118       this.bytes = bytes;
119       this.asInt = asInt;
120       this.asLong = asLong;
121       this.toString = toString;
122     }
123   }
124 }
125