Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import java.util.zip.CRC32;
     18 import java.util.Random;
     19 import java.nio.ByteBuffer;
     20 
     21 /**
     22  * The ART compiler can use intrinsics for the java.util.zip.CRC32 methods:
     23  *   private native static int update(int crc, int b)
     24  *   private native static int updateBytes(int crc, byte[] b, int off, int len)
     25  *
     26  * As the methods are private it is not possible to check the use of intrinsics
     27  * for them directly.
     28  * The tests check that correct checksums are produced.
     29  */
     30 public class Main {
     31   public Main() {
     32   }
     33 
     34   public static long CRC32Byte(int value) {
     35     CRC32 crc32 = new CRC32();
     36     crc32.update(value);
     37     return crc32.getValue();
     38   }
     39 
     40   public static long CRC32BytesUsingUpdateInt(int... values) {
     41     CRC32 crc32 = new CRC32();
     42     for (int value : values) {
     43       crc32.update(value);
     44     }
     45     return crc32.getValue();
     46   }
     47 
     48   public static void assertEqual(long expected, long actual) {
     49     if (expected != actual) {
     50       throw new Error("Expected: " + expected + ", found: " + actual);
     51     }
     52   }
     53 
     54   private static void assertEqual(boolean expected, boolean actual) {
     55     if (expected != actual) {
     56       throw new Error("Expected: " + expected + ", found: " + actual);
     57     }
     58   }
     59 
     60   private static void TestCRC32Update() {
     61     // public void update(int b)
     62     //
     63     // Tests for checksums of the byte 0x0
     64     // Check that only the low eight bits of the argument are used.
     65     assertEqual(0xD202EF8DL, CRC32Byte(0x0));
     66     assertEqual(0xD202EF8DL, CRC32Byte(0x0100));
     67     assertEqual(0xD202EF8DL, CRC32Byte(0x010000));
     68     assertEqual(0xD202EF8DL, CRC32Byte(0x01000000));
     69     assertEqual(0xD202EF8DL, CRC32Byte(0xff00));
     70     assertEqual(0xD202EF8DL, CRC32Byte(0xffff00));
     71     assertEqual(0xD202EF8DL, CRC32Byte(0xffffff00));
     72     assertEqual(0xD202EF8DL, CRC32Byte(0x1200));
     73     assertEqual(0xD202EF8DL, CRC32Byte(0x123400));
     74     assertEqual(0xD202EF8DL, CRC32Byte(0x12345600));
     75     assertEqual(0xD202EF8DL, CRC32Byte(Integer.MIN_VALUE));
     76 
     77     // Tests for checksums of the byte 0x1
     78     // Check that only the low eight bits of the argument are used.
     79     assertEqual(0xA505DF1BL, CRC32Byte(0x1));
     80     assertEqual(0xA505DF1BL, CRC32Byte(0x0101));
     81     assertEqual(0xA505DF1BL, CRC32Byte(0x010001));
     82     assertEqual(0xA505DF1BL, CRC32Byte(0x01000001));
     83     assertEqual(0xA505DF1BL, CRC32Byte(0xff01));
     84     assertEqual(0xA505DF1BL, CRC32Byte(0xffff01));
     85     assertEqual(0xA505DF1BL, CRC32Byte(0xffffff01));
     86     assertEqual(0xA505DF1BL, CRC32Byte(0x1201));
     87     assertEqual(0xA505DF1BL, CRC32Byte(0x123401));
     88     assertEqual(0xA505DF1BL, CRC32Byte(0x12345601));
     89 
     90     // Tests for checksums of the byte 0x0f
     91     // Check that only the low eight bits of the argument are used.
     92     assertEqual(0x42BDF21CL, CRC32Byte(0x0f));
     93     assertEqual(0x42BDF21CL, CRC32Byte(0x010f));
     94     assertEqual(0x42BDF21CL, CRC32Byte(0x01000f));
     95     assertEqual(0x42BDF21CL, CRC32Byte(0x0100000f));
     96     assertEqual(0x42BDF21CL, CRC32Byte(0xff0f));
     97     assertEqual(0x42BDF21CL, CRC32Byte(0xffff0f));
     98     assertEqual(0x42BDF21CL, CRC32Byte(0xffffff0f));
     99     assertEqual(0x42BDF21CL, CRC32Byte(0x120f));
    100     assertEqual(0x42BDF21CL, CRC32Byte(0x12340f));
    101     assertEqual(0x42BDF21CL, CRC32Byte(0x1234560f));
    102 
    103     // Tests for checksums of the byte 0xff
    104     // Check that only the low eight bits of the argument are used.
    105     assertEqual(0xFF000000L, CRC32Byte(0x00ff));
    106     assertEqual(0xFF000000L, CRC32Byte(0x01ff));
    107     assertEqual(0xFF000000L, CRC32Byte(0x0100ff));
    108     assertEqual(0xFF000000L, CRC32Byte(0x010000ff));
    109     assertEqual(0xFF000000L, CRC32Byte(0x0000ffff));
    110     assertEqual(0xFF000000L, CRC32Byte(0x00ffffff));
    111     assertEqual(0xFF000000L, CRC32Byte(0xffffffff));
    112     assertEqual(0xFF000000L, CRC32Byte(0x12ff));
    113     assertEqual(0xFF000000L, CRC32Byte(0x1234ff));
    114     assertEqual(0xFF000000L, CRC32Byte(0x123456ff));
    115     assertEqual(0xFF000000L, CRC32Byte(Integer.MAX_VALUE));
    116 
    117     // Tests for sequences
    118     // Check that only the low eight bits of the values are used.
    119     assertEqual(0xFF41D912L, CRC32BytesUsingUpdateInt(0, 0, 0));
    120     assertEqual(0xFF41D912L,
    121                 CRC32BytesUsingUpdateInt(0x0100, 0x010000, 0x01000000));
    122     assertEqual(0xFF41D912L,
    123                 CRC32BytesUsingUpdateInt(0xff00, 0xffff00, 0xffffff00));
    124     assertEqual(0xFF41D912L,
    125                 CRC32BytesUsingUpdateInt(0x1200, 0x123400, 0x12345600));
    126 
    127     assertEqual(0x909FB2F2L, CRC32BytesUsingUpdateInt(1, 1, 1));
    128     assertEqual(0x909FB2F2L,
    129                 CRC32BytesUsingUpdateInt(0x0101, 0x010001, 0x01000001));
    130     assertEqual(0x909FB2F2L,
    131                 CRC32BytesUsingUpdateInt(0xff01, 0xffff01, 0xffffff01));
    132     assertEqual(0x909FB2F2L,
    133                 CRC32BytesUsingUpdateInt(0x1201, 0x123401, 0x12345601));
    134 
    135     assertEqual(0xE33A9F71L, CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f));
    136     assertEqual(0xE33A9F71L,
    137                 CRC32BytesUsingUpdateInt(0x010f, 0x01000f, 0x0100000f));
    138     assertEqual(0xE33A9F71L,
    139                 CRC32BytesUsingUpdateInt(0xff0f, 0xffff0f, 0xffffff0f));
    140     assertEqual(0xE33A9F71L,
    141                 CRC32BytesUsingUpdateInt(0x120f, 0x12340f, 0x1234560f));
    142 
    143     assertEqual(0xFFFFFF00L, CRC32BytesUsingUpdateInt(0x0ff, 0x0ff, 0x0ff));
    144     assertEqual(0xFFFFFF00L,
    145                 CRC32BytesUsingUpdateInt(0x01ff, 0x0100ff, 0x010000ff));
    146     assertEqual(0xFFFFFF00L,
    147                 CRC32BytesUsingUpdateInt(0x00ffff, 0x00ffffff, 0xffffffff));
    148     assertEqual(0xFFFFFF00L,
    149                 CRC32BytesUsingUpdateInt(0x12ff, 0x1234ff, 0x123456ff));
    150 
    151     assertEqual(0xB6CC4292L, CRC32BytesUsingUpdateInt(0x01, 0x02));
    152 
    153     assertEqual(0xB2DE047CL,
    154                 CRC32BytesUsingUpdateInt(0x0, -1, Integer.MIN_VALUE, Integer.MAX_VALUE));
    155   }
    156 
    157   private static long CRC32ByteArray(byte[] bytes, int off, int len) {
    158     CRC32 crc32 = new CRC32();
    159     crc32.update(bytes, off, len);
    160     return crc32.getValue();
    161   }
    162 
    163   // This is used to test we generate correct code for constant offsets.
    164   // In this case the offset is 0.
    165   private static long CRC32ByteArray(byte[] bytes) {
    166     CRC32 crc32 = new CRC32();
    167     crc32.update(bytes);
    168     return crc32.getValue();
    169   }
    170 
    171   private static long CRC32ByteAndByteArray(int value, byte[] bytes) {
    172     CRC32 crc32 = new CRC32();
    173     crc32.update(value);
    174     crc32.update(bytes);
    175     return crc32.getValue();
    176   }
    177 
    178   private static long CRC32ByteArrayAndByte(byte[] bytes, int value) {
    179     CRC32 crc32 = new CRC32();
    180     crc32.update(bytes);
    181     crc32.update(value);
    182     return crc32.getValue();
    183   }
    184 
    185   private static boolean CRC32ByteArrayThrowsAIOOBE(byte[] bytes, int off, int len) {
    186     try {
    187       CRC32 crc32 = new CRC32();
    188       crc32.update(bytes, off, len);
    189     } catch (ArrayIndexOutOfBoundsException ex) {
    190       return true;
    191     }
    192     return false;
    193   }
    194 
    195   private static boolean CRC32ByteArrayThrowsNPE() {
    196     try {
    197       CRC32 crc32 = new CRC32();
    198       crc32.update(null, 0, 0);
    199       return false;
    200     } catch (NullPointerException e) {}
    201 
    202     try {
    203       CRC32 crc32 = new CRC32();
    204       crc32.update(null, 1, 2);
    205       return false;
    206     } catch (NullPointerException e) {}
    207 
    208     try {
    209       CRC32 crc32 = new CRC32();
    210       crc32.update((byte[])null);
    211       return false;
    212     } catch (NullPointerException e) {}
    213 
    214     return true;
    215   }
    216 
    217   private static long CRC32BytesUsingUpdateInt(byte[] bytes, int off, int len) {
    218     CRC32 crc32 = new CRC32();
    219     while (len-- > 0) {
    220       crc32.update(bytes[off++]);
    221     }
    222     return crc32.getValue();
    223   }
    224 
    225   private static void TestCRC32UpdateBytes() {
    226     assertEqual(0L, CRC32ByteArray(new byte[] {}));
    227     assertEqual(0L, CRC32ByteArray(new byte[] {}, 0, 0));
    228     assertEqual(0L, CRC32ByteArray(new byte[] {0}, 0, 0));
    229     assertEqual(0L, CRC32ByteArray(new byte[] {0}, 1, 0));
    230     assertEqual(0L, CRC32ByteArray(new byte[] {0, 0}, 1, 0));
    231 
    232     assertEqual(true, CRC32ByteArrayThrowsNPE());
    233     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, -1, 0));
    234     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, -1, 1));
    235     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, 0, -1));
    236     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, -1));
    237     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 1, 0));
    238     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, -1, 1));
    239     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 1, -1));
    240     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, 1));
    241     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 0, 10));
    242     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0}, 0, 10));
    243     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {}, 10, 10));
    244     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0, 0, 0, 0}, 2, 3));
    245     assertEqual(true, CRC32ByteArrayThrowsAIOOBE(new byte[] {0, 0, 0, 0}, 3, 2));
    246 
    247     assertEqual(CRC32Byte(0), CRC32ByteArray(new byte[] {0}));
    248     assertEqual(CRC32Byte(0), CRC32ByteArray(new byte[] {0}, 0, 1));
    249     assertEqual(CRC32Byte(1), CRC32ByteArray(new byte[] {1}));
    250     assertEqual(CRC32Byte(1), CRC32ByteArray(new byte[] {1}, 0, 1));
    251     assertEqual(CRC32Byte(0x0f), CRC32ByteArray(new byte[] {0x0f}));
    252     assertEqual(CRC32Byte(0x0f), CRC32ByteArray(new byte[] {0x0f}, 0, 1));
    253     assertEqual(CRC32Byte(0xff), CRC32ByteArray(new byte[] {-1}));
    254     assertEqual(CRC32Byte(0xff), CRC32ByteArray(new byte[] {-1}, 0, 1));
    255     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    256                 CRC32ByteArray(new byte[] {0, 0, 0}));
    257     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    258                 CRC32ByteArray(new byte[] {0, 0, 0}, 0, 3));
    259     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    260                 CRC32ByteArray(new byte[] {1, 1, 1}));
    261     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    262                 CRC32ByteArray(new byte[] {1, 1, 1}, 0, 3));
    263     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    264                 CRC32ByteArray(new byte[] {0x0f, 0x0f, 0x0f}));
    265     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    266                 CRC32ByteArray(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3));
    267     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    268                 CRC32ByteArray(new byte[] {-1, -1, -1}));
    269     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    270                 CRC32ByteArray(new byte[] {-1, -1, -1}, 0, 3));
    271     assertEqual(CRC32BytesUsingUpdateInt(1, 2),
    272                 CRC32ByteArray(new byte[] {1, 2}));
    273     assertEqual(CRC32BytesUsingUpdateInt(1, 2),
    274                 CRC32ByteArray(new byte[] {1, 2}, 0, 2));
    275     assertEqual(
    276         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    277         CRC32ByteArray(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}));
    278     assertEqual(
    279         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    280         CRC32ByteArray(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4));
    281 
    282     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    283                 CRC32ByteAndByteArray(0, new byte[] {0, 0}));
    284     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    285                 CRC32ByteAndByteArray(1, new byte[] {1, 1}));
    286     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    287                 CRC32ByteAndByteArray(0x0f, new byte[] {0x0f, 0x0f}));
    288     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    289                 CRC32ByteAndByteArray(-1, new byte[] {-1, -1}));
    290     assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3),
    291                 CRC32ByteAndByteArray(1, new byte[] {2, 3}));
    292     assertEqual(
    293         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    294         CRC32ByteAndByteArray(0, new byte[] {-1, Byte.MIN_VALUE, Byte.MAX_VALUE}));
    295 
    296     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    297                 CRC32ByteArrayAndByte(new byte[] {0, 0}, 0));
    298     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    299                 CRC32ByteArrayAndByte(new byte[] {1, 1}, 1));
    300     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    301                 CRC32ByteArrayAndByte(new byte[] {0x0f, 0x0f}, 0x0f));
    302     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    303                 CRC32ByteArrayAndByte(new byte[] {-1, -1}, -1));
    304     assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3),
    305                 CRC32ByteArrayAndByte(new byte[] {1, 2}, 3));
    306     assertEqual(
    307         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    308         CRC32ByteArrayAndByte(new byte[] {0, -1, Byte.MIN_VALUE}, Byte.MAX_VALUE));
    309 
    310     byte[] bytes = new byte[128 * 1024];
    311     Random rnd = new Random(0);
    312     rnd.nextBytes(bytes);
    313 
    314     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, bytes.length),
    315                 CRC32ByteArray(bytes));
    316     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024),
    317                 CRC32ByteArray(bytes, 0, 8 * 1024));
    318 
    319     int off = rnd.nextInt(bytes.length / 2);
    320     for (int len = 0; len <= 16; ++len) {
    321       assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    322                   CRC32ByteArray(bytes, off, len));
    323     }
    324 
    325     // Check there are no issues with unaligned accesses.
    326     for (int o = 1; o < 8; ++o) {
    327       for (int l = 0; l <= 16; ++l) {
    328         assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l),
    329                     CRC32ByteArray(bytes, o, l));
    330       }
    331     }
    332 
    333     int len = bytes.length / 2;
    334     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1),
    335                 CRC32ByteArray(bytes, 0, len - 1));
    336     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len),
    337                 CRC32ByteArray(bytes, 0, len));
    338     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1),
    339                 CRC32ByteArray(bytes, 0, len + 1));
    340 
    341     len = rnd.nextInt(bytes.length + 1);
    342     off = rnd.nextInt(bytes.length - len);
    343     assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    344                 CRC32ByteArray(bytes, off, len));
    345   }
    346 
    347   private static long CRC32ByteBuffer(byte[] bytes, int off, int len) {
    348     ByteBuffer buf = ByteBuffer.wrap(bytes, 0, off + len);
    349     buf.position(off);
    350     CRC32 crc32 = new CRC32();
    351     crc32.update(buf);
    352     return crc32.getValue();
    353   }
    354 
    355   private static void TestCRC32UpdateByteBuffer() {
    356     assertEqual(0L, CRC32ByteBuffer(new byte[] {}, 0, 0));
    357     assertEqual(0L, CRC32ByteBuffer(new byte[] {0}, 0, 0));
    358     assertEqual(0L, CRC32ByteBuffer(new byte[] {0}, 1, 0));
    359     assertEqual(0L, CRC32ByteBuffer(new byte[] {0, 0}, 1, 0));
    360 
    361     assertEqual(CRC32Byte(0), CRC32ByteBuffer(new byte[] {0}, 0, 1));
    362     assertEqual(CRC32Byte(1), CRC32ByteBuffer(new byte[] {1}, 0, 1));
    363     assertEqual(CRC32Byte(0x0f), CRC32ByteBuffer(new byte[] {0x0f}, 0, 1));
    364     assertEqual(CRC32Byte(0xff), CRC32ByteBuffer(new byte[] {-1}, 0, 1));
    365     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    366                 CRC32ByteBuffer(new byte[] {0, 0, 0}, 0, 3));
    367     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    368                 CRC32ByteBuffer(new byte[] {1, 1, 1}, 0, 3));
    369     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    370                 CRC32ByteBuffer(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3));
    371     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    372                 CRC32ByteBuffer(new byte[] {-1, -1, -1}, 0, 3));
    373     assertEqual(CRC32BytesUsingUpdateInt(1, 2),
    374                 CRC32ByteBuffer(new byte[] {1, 2}, 0, 2));
    375     assertEqual(
    376         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    377         CRC32ByteBuffer(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4));
    378 
    379     byte[] bytes = new byte[128 * 1024];
    380     Random rnd = new Random(0);
    381     rnd.nextBytes(bytes);
    382 
    383     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024),
    384                 CRC32ByteBuffer(bytes, 0, 8 * 1024));
    385 
    386     int off = rnd.nextInt(bytes.length / 2);
    387     for (int len = 0; len <= 16; ++len) {
    388       assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    389                   CRC32ByteBuffer(bytes, off, len));
    390     }
    391 
    392     // Check there are no issues with unaligned accesses.
    393     for (int o = 1; o < 8; ++o) {
    394       for (int l = 0; l <= 16; ++l) {
    395         assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l),
    396                     CRC32ByteBuffer(bytes, o, l));
    397       }
    398     }
    399 
    400     int len = bytes.length / 2;
    401     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1),
    402                 CRC32ByteBuffer(bytes, 0, len - 1));
    403     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len),
    404                 CRC32ByteBuffer(bytes, 0, len));
    405     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1),
    406                 CRC32ByteBuffer(bytes, 0, len + 1));
    407 
    408     len = rnd.nextInt(bytes.length + 1);
    409     off = rnd.nextInt(bytes.length - len);
    410     assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    411                 CRC32ByteBuffer(bytes, off, len));
    412   }
    413 
    414   private static long CRC32DirectByteBuffer(byte[] bytes, int off, int len) {
    415     final int total_len = off + len;
    416     ByteBuffer buf = ByteBuffer.allocateDirect(total_len).put(bytes, 0, total_len);
    417     buf.position(off);
    418     CRC32 crc32 = new CRC32();
    419     crc32.update(buf);
    420     return crc32.getValue();
    421   }
    422 
    423   private static long CRC32ByteAndDirectByteBuffer(int value, byte[] bytes) {
    424     ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length).put(bytes);
    425     buf.position(0);
    426     CRC32 crc32 = new CRC32();
    427     crc32.update(value);
    428     crc32.update(buf);
    429     return crc32.getValue();
    430   }
    431 
    432   private static long CRC32DirectByteBufferAndByte(byte[] bytes, int value) {
    433     ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length).put(bytes);
    434     buf.position(0);
    435     CRC32 crc32 = new CRC32();
    436     crc32.update(buf);
    437     crc32.update(value);
    438     return crc32.getValue();
    439   }
    440 
    441   private static void TestCRC32UpdateDirectByteBuffer() {
    442     assertEqual(0L, CRC32DirectByteBuffer(new byte[] {}, 0, 0));
    443     assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0}, 0, 0));
    444     assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0}, 1, 0));
    445     assertEqual(0L, CRC32DirectByteBuffer(new byte[] {0, 0}, 1, 0));
    446 
    447     assertEqual(CRC32Byte(0), CRC32DirectByteBuffer(new byte[] {0}, 0, 1));
    448     assertEqual(CRC32Byte(1), CRC32DirectByteBuffer(new byte[] {1}, 0, 1));
    449     assertEqual(CRC32Byte(0x0f), CRC32DirectByteBuffer(new byte[] {0x0f}, 0, 1));
    450     assertEqual(CRC32Byte(0xff), CRC32DirectByteBuffer(new byte[] {-1}, 0, 1));
    451     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    452                 CRC32DirectByteBuffer(new byte[] {0, 0, 0}, 0, 3));
    453     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    454                 CRC32DirectByteBuffer(new byte[] {1, 1, 1}, 0, 3));
    455     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    456                 CRC32DirectByteBuffer(new byte[] {0x0f, 0x0f, 0x0f}, 0, 3));
    457     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    458                 CRC32DirectByteBuffer(new byte[] {-1, -1, -1}, 0, 3));
    459     assertEqual(CRC32BytesUsingUpdateInt(1, 2),
    460                 CRC32DirectByteBuffer(new byte[] {1, 2}, 0, 2));
    461     assertEqual(
    462         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    463         CRC32DirectByteBuffer(new byte[] {0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE}, 0, 4));
    464 
    465     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    466                 CRC32ByteAndDirectByteBuffer(0, new byte[] {0, 0}));
    467     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    468                 CRC32ByteAndDirectByteBuffer(1, new byte[] {1, 1}));
    469     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    470                 CRC32ByteAndDirectByteBuffer(0x0f, new byte[] {0x0f, 0x0f}));
    471     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    472                 CRC32ByteAndDirectByteBuffer(-1, new byte[] {-1, -1}));
    473     assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3),
    474                 CRC32ByteAndDirectByteBuffer(1, new byte[] {2, 3}));
    475     assertEqual(
    476         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    477         CRC32ByteAndDirectByteBuffer(0, new byte[] {-1, Byte.MIN_VALUE, Byte.MAX_VALUE}));
    478 
    479     assertEqual(CRC32BytesUsingUpdateInt(0, 0, 0),
    480                 CRC32DirectByteBufferAndByte(new byte[] {0, 0}, 0));
    481     assertEqual(CRC32BytesUsingUpdateInt(1, 1, 1),
    482                 CRC32DirectByteBufferAndByte(new byte[] {1, 1}, 1));
    483     assertEqual(CRC32BytesUsingUpdateInt(0x0f, 0x0f, 0x0f),
    484                 CRC32DirectByteBufferAndByte(new byte[] {0x0f, 0x0f}, 0x0f));
    485     assertEqual(CRC32BytesUsingUpdateInt(0xff, 0xff, 0xff),
    486                 CRC32DirectByteBufferAndByte(new byte[] {-1, -1}, -1));
    487     assertEqual(CRC32BytesUsingUpdateInt(1, 2, 3),
    488                 CRC32DirectByteBufferAndByte(new byte[] {1, 2}, 3));
    489     assertEqual(
    490         CRC32BytesUsingUpdateInt(0, -1, Byte.MIN_VALUE, Byte.MAX_VALUE),
    491         CRC32DirectByteBufferAndByte(new byte[] {0, -1, Byte.MIN_VALUE}, Byte.MAX_VALUE));
    492 
    493     byte[] bytes = new byte[128 * 1024];
    494     Random rnd = new Random(0);
    495     rnd.nextBytes(bytes);
    496 
    497     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, bytes.length),
    498                 CRC32DirectByteBuffer(bytes, 0, bytes.length));
    499     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, 8 * 1024),
    500                 CRC32DirectByteBuffer(bytes, 0, 8 * 1024));
    501 
    502     int off = rnd.nextInt(bytes.length / 2);
    503     for (int len = 0; len <= 16; ++len) {
    504       assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    505                   CRC32DirectByteBuffer(bytes, off, len));
    506     }
    507 
    508     // Check there are no issues with unaligned accesses.
    509     for (int o = 1; o < 8; ++o) {
    510       for (int l = 0; l <= 16; ++l) {
    511         assertEqual(CRC32BytesUsingUpdateInt(bytes, o, l),
    512                     CRC32DirectByteBuffer(bytes, o, l));
    513       }
    514     }
    515 
    516     int len = bytes.length / 2;
    517     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len - 1),
    518                 CRC32DirectByteBuffer(bytes, 0, len - 1));
    519     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len),
    520                 CRC32DirectByteBuffer(bytes, 0, len));
    521     assertEqual(CRC32BytesUsingUpdateInt(bytes, 0, len + 1),
    522                 CRC32DirectByteBuffer(bytes, 0, len + 1));
    523 
    524     len = rnd.nextInt(bytes.length + 1);
    525     off = rnd.nextInt(bytes.length - len);
    526     assertEqual(CRC32BytesUsingUpdateInt(bytes, off, len),
    527                 CRC32DirectByteBuffer(bytes, off, len));
    528   }
    529 
    530   public static void main(String args[]) {
    531     TestCRC32Update();
    532     TestCRC32UpdateBytes();
    533     TestCRC32UpdateByteBuffer();
    534     TestCRC32UpdateDirectByteBuffer();
    535   }
    536 }
    537