1/*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * Base class for Checksum tests
26 */
27import java.nio.ByteBuffer;
28import java.nio.ByteOrder;
29import java.nio.charset.StandardCharsets;
30import java.util.zip.Checksum;
31
32public class ChecksumBase {
33
34    private static final byte[] BYTES_123456789 = "123456789".getBytes(StandardCharsets.US_ASCII);
35
36    public static void testAll(Checksum checksum, long expected) {
37        testBytes(checksum, expected);
38        testByteArray(checksum, expected);
39        testWrappedByteBuffer(checksum, expected);
40        testReadonlyByteBuffer(checksum, expected);
41        testDirectByteBuffer(checksum, expected);
42        testByteArrayOffset(checksum, expected);
43        testDirectByteBufferOffset(checksum, expected);
44        testLittleEndianDirectByteBufferOffset(checksum, expected);
45        testWrappedByteBufferOffset(checksum, expected);
46        testLittleEndianWrappedByteBufferOffset(checksum, expected);
47        testReadonlyByteBufferOffset(checksum, expected);
48        testLittleEndianReadonlyByteBufferOffset(checksum, expected);
49    }
50
51    private static void testBytes(Checksum checksum, long expected) {
52        checksum.reset();
53        for (byte bits : BYTES_123456789) {
54            checksum.update(bits);
55        }
56        checkChecksum(checksum, expected);
57    }
58
59    private static void testByteArray(Checksum checksum, long expected) {
60        checksum.reset();
61        checksum.update(BYTES_123456789);
62        checkChecksum(checksum, expected);
63    }
64
65    private static void testWrappedByteBuffer(Checksum checksum, long expected) {
66        checksum.reset();
67        ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789);
68        checksum.update(bb);
69        checkChecksum(checksum, expected);
70    }
71
72    private static void testReadonlyByteBuffer(Checksum checksum, long expected) {
73        checksum.reset();
74        ByteBuffer bb = ByteBuffer.wrap(BYTES_123456789).asReadOnlyBuffer();
75        checksum.update(bb);
76        checkChecksum(checksum, expected);
77    }
78
79    private static void testDirectByteBuffer(Checksum checksum, long expected) {
80        checksum.reset();
81        ByteBuffer bb = ByteBuffer.allocateDirect(BYTES_123456789.length);
82        bb.put(BYTES_123456789);
83        bb.rewind();
84        checksum.update(bb);
85        checkChecksum(checksum, expected);
86    }
87
88    private static void checkChecksum(Checksum checksum, long expected) {
89        if (checksum.getValue() != expected) {
90            throw new RuntimeException("Calculated checksum result was invalid."
91                    + " Expected " + Long.toHexString(expected)
92                    + ", but got " + Long.toHexString(checksum.getValue()) + ".");
93        }
94    }
95
96    private static void testByteArrayOffset(Checksum checksum, long expected) {
97        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
98        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
99            checksum.reset();
100            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
101            checksum.update(unaligned_bytes_123456789, i, BYTES_123456789.length);
102            checkChecksumOffset(checksum, expected, i);
103        }
104    }
105
106    private static void testDirectByteBufferOffset(Checksum checksum, long expected) {
107        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
108        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
109            checksum.reset();
110            ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
111            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
112            bb.put(unaligned_bytes_123456789);
113            bb.position(i);
114            bb.limit(i + BYTES_123456789.length);
115            checksum.update(bb);
116            checkChecksumOffset(checksum, expected, i);
117        }
118    }
119
120    private static void testLittleEndianDirectByteBufferOffset(Checksum checksum, long expected) {
121        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
122        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
123            checksum.reset();
124            ByteBuffer bb = ByteBuffer.allocateDirect(unaligned_bytes_123456789.length);
125            bb.order(ByteOrder.LITTLE_ENDIAN);
126            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
127            bb.put(unaligned_bytes_123456789);
128            bb.position(i);
129            bb.limit(i + BYTES_123456789.length);
130            checksum.update(bb);
131            checkChecksumOffset(checksum, expected, i);
132        }
133    }
134
135    private static void testWrappedByteBufferOffset(Checksum checksum, long expected) {
136        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
137        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
138            checksum.reset();
139            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
140            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
141            bb.position(i);
142            bb.limit(i + BYTES_123456789.length);
143            checksum.update(bb);
144            checkChecksumOffset(checksum, expected, i);
145        }
146    }
147
148    private static void testLittleEndianWrappedByteBufferOffset(Checksum checksum, long expected) {
149        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
150        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
151            checksum.reset();
152            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
153            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789);
154            bb.order(ByteOrder.LITTLE_ENDIAN);
155            bb.position(i);
156            bb.limit(i + BYTES_123456789.length);
157            checksum.update(bb);
158            checkChecksumOffset(checksum, expected, i);
159        }
160    }
161
162    private static void testReadonlyByteBufferOffset(Checksum checksum, long expected) {
163        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
164        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
165            checksum.reset();
166            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
167            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
168            bb.position(i);
169            bb.limit(i + BYTES_123456789.length);
170            checksum.update(bb);
171            checkChecksumOffset(checksum, expected, i);
172        }
173    }
174
175    private static void testLittleEndianReadonlyByteBufferOffset(Checksum checksum, long expected) {
176        byte[] unaligned_bytes_123456789 = new byte[BYTES_123456789.length + 64];
177        for (int i = 0; i < unaligned_bytes_123456789.length - BYTES_123456789.length; i++) {
178            checksum.reset();
179            System.arraycopy(BYTES_123456789, 0, unaligned_bytes_123456789, i, BYTES_123456789.length);
180            ByteBuffer bb = ByteBuffer.wrap(unaligned_bytes_123456789).asReadOnlyBuffer();
181            bb.order(ByteOrder.LITTLE_ENDIAN);
182            bb.position(i);
183            bb.limit(i + BYTES_123456789.length);
184            checksum.update(bb);
185            checkChecksumOffset(checksum, expected, i);
186        }
187    }
188
189    private static void checkChecksumOffset(Checksum checksum, long expected, int offset) {
190        if (checksum.getValue() != expected) {
191            throw new RuntimeException("Calculated CRC32C result was invalid. Array offset "
192                    + offset + ". Expected: " + Long.toHexString(expected) + ", Got: "
193                    + Long.toHexString(checksum.getValue()));
194        }
195    }
196}
197