View Javadoc
1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package com.google.common.hash;
16  
17  import static com.google.common.base.Charsets.UTF_8;
18  
19  import junit.framework.TestCase;
20  
21  import java.util.Arrays;
22  
23  /**
24   * Unit tests for {@link Crc32c}. Known test values are from RFC 3720, Section B.4.
25   *
26   * @author Patrick Costello
27   * @author Kurt Alfred Kluever
28   */
29  public class Crc32cHashFunctionTest extends TestCase {
30  
31    public void testZeros() {
32      // Test 32 byte array of 0x00.
33      byte[] zeros = new byte[32];
34      Arrays.fill(zeros, (byte) 0x00);
35      assertCrc(0x8a9136aa, zeros);
36    }
37  
38    public void testFull() {
39      // Test 32 byte array of 0xFF.
40      byte[] fulls = new byte[32];
41      Arrays.fill(fulls, (byte) 0xFF);
42      assertCrc(0x62a8ab43, fulls);
43    }
44  
45    public void testAscending() {
46      // Test 32 byte arrays of ascending.
47      byte[] ascending = new byte[32];
48      for (int i = 0; i < 32; i++) {
49        ascending[i] = (byte) i;
50      }
51      assertCrc(0x46dd794e, ascending);
52    }
53  
54    public void testDescending() {
55      // Test 32 byte arrays of descending.
56      byte[] descending = new byte[32];
57      for (int i = 0; i < 32; i++) {
58        descending[i] = (byte) (31 - i);
59      }
60      assertCrc(0x113fdb5c, descending);
61    }
62  
63    public void testScsiReadCommad() {
64      // Test SCSI read command.
65      byte[] scsiReadCommand = new byte[] {
66          0x01, (byte) 0xc0, 0x00, 0x00,
67          0x00, 0x00, 0x00, 0x00,
68          0x00, 0x00, 0x00, 0x00,
69          0x00, 0x00, 0x00, 0x00,
70          0x14, 0x00, 0x00, 0x00,
71          0x00, 0x00, 0x04, 0x00,
72          0x00, 0x00, 0x00, 0x14,
73          0x00, 0x00, 0x00, 0x18,
74          0x28, 0x00, 0x00, 0x00,
75          0x00, 0x00, 0x00, 0x00,
76          0x02, 0x00, 0x00, 0x00,
77          0x00, 0x00, 0x00, 0x00 };
78      assertCrc(0xd9963a56, scsiReadCommand);
79    }
80  
81    // Known values from http://www.evanjones.ca/crc32c.html
82    public void testSomeOtherKnownValues() {
83      assertCrc(0x22620404, "The quick brown fox jumps over the lazy dog".getBytes(UTF_8));
84      assertCrc(0xE3069283, "123456789".getBytes(UTF_8));
85      assertCrc(0xf3dbd4fe, "1234567890".getBytes(UTF_8));
86      assertCrc(0xBFE92A83, "23456789".getBytes(UTF_8));
87    }
88  
89    /**
90     * Verfies that the crc of an array of byte data matches the expected value.
91     *
92     * @param expectedCrc the expected crc value.
93     * @param data the data to run the checksum on.
94     */
95    private static void assertCrc(int expectedCrc, byte[] data) {
96      int actualCrc = Hashing.crc32c().hashBytes(data).asInt();
97      assertEquals(expectedCrc, actualCrc);
98    }
99  
100   // From RFC 3720, Section 12.1, the polynomial generator is 0x11EDC6F41.
101   // We calculate the constant below by:
102   //   1. Omitting the most significant bit (because it's always 1). => 0x1EDC6F41
103   //   2. Flipping the bits of the constant so we can process a byte at a time. => 0x82F63B78
104   private static final int CRC32C_GENERATOR = 0x1EDC6F41;  // 0x11EDC6F41
105   private static final int CRC32C_GENERATOR_FLIPPED = Integer.reverse(CRC32C_GENERATOR);
106 
107   public void testCrc32cLookupTable() {
108     // See Hacker's Delight 2nd Edition, Figure 14-7.
109     int[] expected = new int[256];
110     for (int i = 0; i < expected.length; i++) {
111       int crc = i;
112       for (int j = 7; j >= 0; j--) {
113         int mask = -(crc & 1);
114         crc = ((crc >>> 1) ^ (CRC32C_GENERATOR_FLIPPED & mask));
115       }
116       expected[i] = crc;
117     }
118 
119     int[] actual = Crc32cHashFunction.Crc32cHasher.CRC_TABLE;
120     assertTrue(
121         "Expected: \n" + Arrays.toString(expected) + "\nActual:\n" + Arrays.toString(actual),
122         Arrays.equals(expected, actual));
123   }
124 }