| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import java.util.zip.CRC32; |
| import java.util.Random; |
| import java.nio.ByteBuffer; |
| |
| /** |
| * The ART compiler can use intrinsics for the java.util.zip.CRC32 methods: |
| * private native static int update(int crc, int b) |
| * private native static int updateBytes(int crc, byte[] b, int off, int len) |
| * |
| * As the methods are private it is not possible to check the use of intrinsics |
| * for them directly. |
| * The tests check that correct checksums are produced. |
| */ |
| public class Main { |
| public Main() { |
| } |
| |
| public static long CRC32Byte(int value) { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(value); |
| return crc32.getValue(); |
| } |
| |
| public static long CRC32BytesUsingUpdateInt(int... values) { |
| CRC32 crc32 = new CRC32(); |
| for (int value : values) { |
| crc32.update(value); |
| } |
| return crc32.getValue(); |
| } |
| |
| public static void assertEqual(long expected, long actual) { |
| if (expected != actual) { |
| throw new Error("Expected: " + expected + ", found: " + actual); |
| } |
| } |
| |
| private static void assertEqual(boolean expected, boolean actual) { |
| if (expected != actual) { |
| throw new Error("Expected: " + expected + ", found: " + actual); |
| } |
| } |
| |
| private static void TestCRC32Update() { |
| // public void update(int b) |
| // |
| // Tests for checksums of the byte 0x0 |
| // Check that only the low eight bits of the argument are used. |
| assertEqual(0xD202EF8DL, CRC32Byte(0x0)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x0100)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x010000)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x01000000)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0xff00)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0xffff00)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0xffffff00)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x1200)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x123400)); |
| assertEqual(0xD202EF8DL, CRC32Byte(0x12345600)); |
| assertEqual(0xD202EF8DL, CRC32Byte(Integer.MIN_VALUE)); |
| |
| // Tests for checksums of the byte 0x1 |
| // Check that only the low eight bits of the argument are used. |
| assertEqual(0xA505DF1BL, CRC32Byte(0x1)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x0101)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x010001)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x01000001)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0xff01)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0xffff01)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0xffffff01)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x1201)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x123401)); |
| assertEqual(0xA505DF1BL, CRC32Byte(0x12345601)); |
| |
| // Tests for checksums of the byte 0x0f |
| // Check that only the low eight bits of the argument are used. |
| assertEqual(0x42BDF21CL, CRC32Byte(0x0f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x010f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x01000f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x0100000f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0xff0f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0xffff0f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0xffffff0f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x120f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x12340f)); |
| assertEqual(0x42BDF21CL, CRC32Byte(0x1234560f)); |
| |
| // Tests for checksums of the byte 0xff |
| // Check that only the low eight bits of the argument are used. |
| assertEqual(0xFF000000L, CRC32Byte(0x00ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x01ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x0100ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x010000ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x0000ffff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x00ffffff)); |
| assertEqual(0xFF000000L, CRC32Byte(0xffffffff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x12ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x1234ff)); |
| assertEqual(0xFF000000L, CRC32Byte(0x123456ff)); |
| assertEqual(0xFF000000L, CRC32Byte(Integer.MAX_VALUE)); |
| |
| // Tests for sequences |
| // Check that only the low eight bits of the values are used. |
| assertEqual(0xFF41D912L, CRC32BytesUsingUpdateInt(0, 0, 0)); |
| assertEqual(0xFF41D912L, |
| CRC32BytesUsingUpdateInt(0x0100, 0x010000, 0x01000000)); |
| assertEqual(0xFF41D912L, |
| CRC32BytesUsingUpdateInt(0xff00, 0xffff00, 0xffffff00)); |
| assertEqual(0xFF41D912L, |
| CRC32BytesUsingUpdateInt(0x1200, 0x123400, 0x12345600)); |
| |
| assertEqual(0x909FB2F2L, CRC32BytesUsingUpdateInt(1, 1, 1)); |
| assertEqual(0x909FB2F2L, |
| CRC32BytesUsingUpdateInt(0x0101, 0x010001, 0x01000001)); |
| assertEqual(0x909FB2F2L, |
| CRC32BytesUsingUpdateInt(0xff01, 0xffff01, 0xffffff01)); |
| assertEqual(0x909FB2F2L, |
| CRC32BytesUsingUpdateInt(0x1201, 0x123401, 0x12345601)); |
| |
| assertEqual(0xE33A9F71L, CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f)); |
| assertEqual(0xE33A9F71L, |
| CRC32BytesUsingUpdateInt(0x010f, 0x01000f, 0x0100000f)); |
| assertEqual(0xE33A9F71L, |
| CRC32BytesUsingUpdateInt(0xff0f, 0xffff0f, 0xffffff0f)); |
| assertEqual(0xE33A9F71L, |
| CRC32BytesUsingUpdateInt(0x120f, 0x12340f, 0x1234560f)); |
| |
| assertEqual(0xFFFFFF00L, CRC32BytesUsingUpdateInt(0x0ff, 0x0ff, 0x0ff)); |
| assertEqual(0xFFFFFF00L, |
| CRC32BytesUsingUpdateInt(0x01ff, 0x0100ff, 0x010000ff)); |
| assertEqual(0xFFFFFF00L, |
| CRC32BytesUsingUpdateInt(0x00ffff, 0x00ffffff, 0xffffffff)); |
| assertEqual(0xFFFFFF00L, |
| CRC32BytesUsingUpdateInt(0x12ff, 0x1234ff, 0x123456ff)); |
| |
| assertEqual(0xB6CC4292L, CRC32BytesUsingUpdateInt(0x01, 0x02)); |
| |
| assertEqual(0xB2DE047CL, |
| CRC32BytesUsingUpdateInt(0x0, -1, Integer.MIN_VALUE, Integer.MAX_VALUE)); |
| } |
| |
| private static long CRC32ByteArray(byte[] bytes, int off, int len) { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(bytes, off, len); |
| return crc32.getValue(); |
| } |
| |
| // This is used to test we generate correct code for constant offsets. |
| // In this case the offset is 0. |
| private static long CRC32ByteArray(byte[] bytes) { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(bytes); |
| return crc32.getValue(); |
| } |
| |
| private static long CRC32ByteAndByteArray(int value, byte[] bytes) { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(value); |
| crc32.update(bytes); |
| return crc32.getValue(); |
| } |
| |
| private static long CRC32ByteArrayAndByte(byte[] bytes, int value) { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(bytes); |
| crc32.update(value); |
| return crc32.getValue(); |
| } |
| |
| private static boolean CRC32ByteArrayThrowsAIOOBE(byte[] bytes, int off, int len) { |
| try { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(bytes, off, len); |
| } catch (ArrayIndexOutOfBoundsException ex) { |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean CRC32ByteArrayThrowsNPE() { |
| try { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(null, 0, 0); |
| return false; |
| } catch (NullPointerException e) {} |
| |
| try { |
| CRC32 crc32 = new CRC32(); |
| crc32.update(null, 1, 2); |
| return false; |
| } catch (NullPointerException e) {} |
| |
| try { |
| CRC32 crc32 = new CRC32(); |
| crc32.update((byte[])null); |
| return false; |
| } catch (NullPointerException e) {} |
| |
| return true; |
| } |
| |
| private static long CRC32BytesUsingUpdateInt(byte[] bytes, int off, int len) { |
| CRC32 crc32 = new CRC32(); |
| while (len-- > 0) { |
| crc32.update(bytes[off++]); |
| } |
| return crc32.getValue(); |
| } |
| |
| private static void TestCRC32UpdateBytes() { |
| assertEqual(0L, CRC32ByteArray(new byte[] {})); |
| assertEqual(0L, CRC32ByteArray(new byte[] {}, 0, 0)); |
| assertEqual(0L, CRC32ByteArray(new byte[] {0}, 0, 0)); |
| assertEqual(0L, CRC32ByteArray(new byte[] {0}, 1, 0)); |
| assertEqual(0L, CRC32ByteArray(new byte[] {0, 0}, 1, 0)); |
| |
| assertEqual(true, CRC32ByteArrayThrowsNPE()); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, -1, 0)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, -1, 1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, 0, -1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, -1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 1, 0)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, -1, 1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 1, -1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, 1)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, 10)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, 0, 10)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 10, 10)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0, 0, 0, 0}, 2, 3)); |
| assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0, 0, 0, 0}, 3, 2)); |
| |
| assertEqual(CRC32Byte(0), CRC32ByteArray(new byte[] {0})); |
| assertEqual(CRC32Byte(0), CRC32ByteArray(new byte[] {0}, 0, 1)); |
| assertEqual(CRC32Byte(1), CRC32ByteArray(new byte[] {1})); |
| assertEqual(CRC32Byte(1), CRC32ByteArray(new byte[] {1}, 0, 1)); |
| assertEqual(CRC32Byte(0x0f), CRC32ByteArray(new byte[] {0x0f})); |
| assertEqual(CRC32Byte(0x0f), CRC32ByteArray(new byte[] {0x0f}, 0, 1)); |
| assertEqual(CRC32Byte(0xff), CRC32ByteArray(new byte[] {-1})); |
| assertEqual(CRC32Byte(0xff), CRC32ByteArray(new byte[] {-1}, 0, 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteArray(new byte[] {0, 0, 0})); |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteArray(new byte[] {0, 0, 0}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteArray(new byte[] {1, 1, 1})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteArray(new byte[] {1, 1, 1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteArray(new byte[] {0x0f, 0x0f, 0x0f})); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteArray(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteArray(new byte[] {-1, -1, -1})); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteArray(new byte[] {-1, -1, -1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2), |
| CRC32ByteArray(new byte[] {1, 2})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2), |
| CRC32ByteArray(new byte[] {1, 2}, 0, 2)); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteArray(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE})); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteArray(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4)); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteAndByteArray(0, new byte[] {0, 0})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteAndByteArray(1, new byte[] {1, 1})); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteAndByteArray(0x0f, new byte[] {0x0f, 0x0f})); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteAndByteArray(-1, new byte[] {-1, -1})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3), |
| CRC32ByteAndByteArray(1, new byte[] {2, 3})); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteAndByteArray(0, new byte[] {-1, Byte.MIN_VALUE, Byte.MAX_VALUE})); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteArrayAndByte(new byte[] {0, 0}, 0)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteArrayAndByte(new byte[] {1, 1}, 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteArrayAndByte(new byte[] {0x0f, 0x0f}, 0x0f)); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteArrayAndByte(new byte[] {-1, -1}, -1)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3), |
| CRC32ByteArrayAndByte(new byte[] {1, 2}, 3)); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteArrayAndByte(new byte[] {0, -1, Byte.MIN_VALUE}, Byte.MAX_VALUE)); |
| |
| byte[] bytes = new byte[128 * 1024]; |
| Random rnd = new Random(0); |
| rnd.nextBytes(bytes); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, bytes.length), |
| CRC32ByteArray(bytes)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024), |
| CRC32ByteArray(bytes, 0, 8 * 1024)); |
| |
| int off = rnd.nextInt(bytes.length / 2); |
| for (int len = 0; len <= 16; ++len) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32ByteArray(bytes, off, len)); |
| } |
| |
| // Check there are no issues with unaligned accesses. |
| for (int o = 1; o < 8; ++o) { |
| for (int l = 0; l <= 16; ++l) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l), |
| CRC32ByteArray(bytes, o, l)); |
| } |
| } |
| |
| int len = bytes.length / 2; |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1), |
| CRC32ByteArray(bytes, 0, len - 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len), |
| CRC32ByteArray(bytes, 0, len)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1), |
| CRC32ByteArray(bytes, 0, len + 1)); |
| |
| len = rnd.nextInt(bytes.length + 1); |
| off = rnd.nextInt(bytes.length - len); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32ByteArray(bytes, off, len)); |
| } |
| |
| private static long CRC32ByteBuffer(byte[] bytes, int off, int len) { |
| ByteBuffer buf = ByteBuffer.wrap(bytes, 0, off + len); |
| buf.position(off); |
| CRC32 crc32 = new CRC32(); |
| crc32.update(buf); |
| return crc32.getValue(); |
| } |
| |
| private static void TestCRC32UpdateByteBuffer() { |
| assertEqual(0L, CRC32ByteBuffer(new byte[] {}, 0, 0)); |
| assertEqual(0L, CRC32ByteBuffer(new byte[] {0}, 0, 0)); |
| assertEqual(0L, CRC32ByteBuffer(new byte[] {0}, 1, 0)); |
| assertEqual(0L, CRC32ByteBuffer(new byte[] {0, 0}, 1, 0)); |
| |
| assertEqual(CRC32Byte(0), CRC32ByteBuffer(new byte[] {0}, 0, 1)); |
| assertEqual(CRC32Byte(1), CRC32ByteBuffer(new byte[] {1}, 0, 1)); |
| assertEqual(CRC32Byte(0x0f), CRC32ByteBuffer(new byte[] {0x0f}, 0, 1)); |
| assertEqual(CRC32Byte(0xff), CRC32ByteBuffer(new byte[] {-1}, 0, 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteBuffer(new byte[] {0, 0, 0}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteBuffer(new byte[] {1, 1, 1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteBuffer(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteBuffer(new byte[] {-1, -1, -1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2), |
| CRC32ByteBuffer(new byte[] {1, 2}, 0, 2)); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteBuffer(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4)); |
| |
| byte[] bytes = new byte[128 * 1024]; |
| Random rnd = new Random(0); |
| rnd.nextBytes(bytes); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024), |
| CRC32ByteBuffer(bytes, 0, 8 * 1024)); |
| |
| int off = rnd.nextInt(bytes.length / 2); |
| for (int len = 0; len <= 16; ++len) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32ByteBuffer(bytes, off, len)); |
| } |
| |
| // Check there are no issues with unaligned accesses. |
| for (int o = 1; o < 8; ++o) { |
| for (int l = 0; l <= 16; ++l) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l), |
| CRC32ByteBuffer(bytes, o, l)); |
| } |
| } |
| |
| int len = bytes.length / 2; |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1), |
| CRC32ByteBuffer(bytes, 0, len - 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len), |
| CRC32ByteBuffer(bytes, 0, len)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1), |
| CRC32ByteBuffer(bytes, 0, len + 1)); |
| |
| len = rnd.nextInt(bytes.length + 1); |
| off = rnd.nextInt(bytes.length - len); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32ByteBuffer(bytes, off, len)); |
| } |
| |
| private static long CRC32DirectByteBuffer(byte[] bytes, int off, int len) { |
| final int total_len = off + len; |
| ByteBuffer buf = ByteBuffer.allocateDirect(total_len).put(bytes, 0, total_len); |
| buf.position(off); |
| CRC32 crc32 = new CRC32(); |
| crc32.update(buf); |
| return crc32.getValue(); |
| } |
| |
| private static long CRC32ByteAndDirectByteBuffer(int value, byte[] bytes) { |
| ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length).put(bytes); |
| buf.position(0); |
| CRC32 crc32 = new CRC32(); |
| crc32.update(value); |
| crc32.update(buf); |
| return crc32.getValue(); |
| } |
| |
| private static long CRC32DirectByteBufferAndByte(byte[] bytes, int value) { |
| ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length).put(bytes); |
| buf.position(0); |
| CRC32 crc32 = new CRC32(); |
| crc32.update(buf); |
| crc32.update(value); |
| return crc32.getValue(); |
| } |
| |
| private static void TestCRC32UpdateDirectByteBuffer() { |
| assertEqual(0L, CRC32DirectByteBuffer(new byte[] {}, 0, 0)); |
| assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0}, 0, 0)); |
| assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0}, 1, 0)); |
| assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0, 0}, 1, 0)); |
| |
| assertEqual(CRC32Byte(0), CRC32DirectByteBuffer(new byte[] {0}, 0, 1)); |
| assertEqual(CRC32Byte(1), CRC32DirectByteBuffer(new byte[] {1}, 0, 1)); |
| assertEqual(CRC32Byte(0x0f), CRC32DirectByteBuffer(new byte[] {0x0f}, 0, 1)); |
| assertEqual(CRC32Byte(0xff), CRC32DirectByteBuffer(new byte[] {-1}, 0, 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32DirectByteBuffer(new byte[] {0, 0, 0}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32DirectByteBuffer(new byte[] {1, 1, 1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32DirectByteBuffer(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32DirectByteBuffer(new byte[] {-1, -1, -1}, 0, 3)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2), |
| CRC32DirectByteBuffer(new byte[] {1, 2}, 0, 2)); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32DirectByteBuffer(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4)); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32ByteAndDirectByteBuffer(0, new byte[] {0, 0})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32ByteAndDirectByteBuffer(1, new byte[] {1, 1})); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32ByteAndDirectByteBuffer(0x0f, new byte[] {0x0f, 0x0f})); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32ByteAndDirectByteBuffer(-1, new byte[] {-1, -1})); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3), |
| CRC32ByteAndDirectByteBuffer(1, new byte[] {2, 3})); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32ByteAndDirectByteBuffer(0, new byte[] {-1, Byte.MIN_VALUE, Byte.MAX_VALUE})); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0), |
| CRC32DirectByteBufferAndByte(new byte[] {0, 0}, 0)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1), |
| CRC32DirectByteBufferAndByte(new byte[] {1, 1}, 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f), |
| CRC32DirectByteBufferAndByte(new byte[] {0x0f, 0x0f}, 0x0f)); |
| assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff), |
| CRC32DirectByteBufferAndByte(new byte[] {-1, -1}, -1)); |
| assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3), |
| CRC32DirectByteBufferAndByte(new byte[] {1, 2}, 3)); |
| assertEqual( |
| CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE), |
| CRC32DirectByteBufferAndByte(new byte[] {0, -1, Byte.MIN_VALUE}, Byte.MAX_VALUE)); |
| |
| byte[] bytes = new byte[128 * 1024]; |
| Random rnd = new Random(0); |
| rnd.nextBytes(bytes); |
| |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, bytes.length), |
| CRC32DirectByteBuffer(bytes, 0, bytes.length)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024), |
| CRC32DirectByteBuffer(bytes, 0, 8 * 1024)); |
| |
| int off = rnd.nextInt(bytes.length / 2); |
| for (int len = 0; len <= 16; ++len) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32DirectByteBuffer(bytes, off, len)); |
| } |
| |
| // Check there are no issues with unaligned accesses. |
| for (int o = 1; o < 8; ++o) { |
| for (int l = 0; l <= 16; ++l) { |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l), |
| CRC32DirectByteBuffer(bytes, o, l)); |
| } |
| } |
| |
| int len = bytes.length / 2; |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1), |
| CRC32DirectByteBuffer(bytes, 0, len - 1)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len), |
| CRC32DirectByteBuffer(bytes, 0, len)); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1), |
| CRC32DirectByteBuffer(bytes, 0, len + 1)); |
| |
| len = rnd.nextInt(bytes.length + 1); |
| off = rnd.nextInt(bytes.length - len); |
| assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len), |
| CRC32DirectByteBuffer(bytes, off, len)); |
| } |
| |
| public static void main(String args[]) { |
| TestCRC32Update(); |
| TestCRC32UpdateBytes(); |
| TestCRC32UpdateByteBuffer(); |
| TestCRC32UpdateDirectByteBuffer(); |
| } |
| } |