• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Main()31    public Main() {
32    }
33  
CRC32Byte(int value)34    public static long CRC32Byte(int value) {
35      CRC32 crc32 = new CRC32();
36      crc32.update(value);
37      return crc32.getValue();
38    }
39  
CRC32BytesUsingUpdateInt(int... values)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  
assertEqual(long expected, long actual)48    public static void assertEqual(long expected, long actual) {
49      if (expected != actual) {
50        throw new Error("Expected: " + expected + ", found: " + actual);
51      }
52    }
53  
assertEqual(boolean expected, boolean actual)54    private static void assertEqual(boolean expected, boolean actual) {
55      if (expected != actual) {
56        throw new Error("Expected: " + expected + ", found: " + actual);
57      }
58    }
59  
TestCRC32Update()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  
CRC32ByteArray(byte[] bytes, int off, int len)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.
CRC32ByteArray(byte[] bytes)165    private static long CRC32ByteArray(byte[] bytes) {
166      CRC32 crc32 = new CRC32();
167      crc32.update(bytes);
168      return crc32.getValue();
169    }
170  
CRC32ByteAndByteArray(int value, byte[] bytes)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  
CRC32ByteArrayAndByte(byte[] bytes, int value)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  
CRC32ByteArrayThrowsAIOOBE(byte[] bytes, int off, int len)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  
CRC32ByteArrayThrowsNPE()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  
CRC32BytesUsingUpdateInt(byte[] bytes, int off, int len)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  
TestCRC32UpdateBytes()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  
CRC32ByteBuffer(byte[] bytes, int off, int len)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  
TestCRC32UpdateByteBuffer()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  
CRC32DirectByteBuffer(byte[] bytes, int off, int len)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  
CRC32ByteAndDirectByteBuffer(int value, byte[] bytes)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  
CRC32DirectByteBufferAndByte(byte[] bytes, int value)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  
TestCRC32UpdateDirectByteBuffer()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  
main(String args[])530    public static void main(String args[]) {
531      TestCRC32Update();
532      TestCRC32UpdateBytes();
533      TestCRC32UpdateByteBuffer();
534      TestCRC32UpdateDirectByteBuffer();
535    }
536  }
537