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 
testZeros()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 
testFull()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 
testAscending()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 
testDescending()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 
testScsiReadCommad()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
testSomeOtherKnownValues()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    */
assertCrc(int expectedCrc, byte[] data)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 
testCrc32cLookupTable()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 }
125