001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.util;
019
020import static org.junit.jupiter.api.Assertions.assertArrayEquals;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022import static org.junit.jupiter.api.Assertions.assertFalse;
023import static org.junit.jupiter.api.Assertions.assertNotNull;
024import static org.junit.jupiter.api.Assertions.assertNotSame;
025import static org.junit.jupiter.api.Assertions.assertTrue;
026import static org.junit.jupiter.api.Assertions.fail;
027
028import java.io.ByteArrayInputStream;
029import java.io.ByteArrayOutputStream;
030import java.io.DataInputStream;
031import java.io.DataOutputStream;
032import java.io.IOException;
033import java.math.BigDecimal;
034import java.nio.ByteBuffer;
035import java.util.ArrayList;
036import java.util.Arrays;
037import java.util.List;
038import java.util.Random;
039import java.util.concurrent.ThreadLocalRandom;
040import org.apache.hadoop.io.WritableUtils;
041import org.junit.jupiter.api.Test;
042import org.slf4j.Logger;
043import org.slf4j.LoggerFactory;
044
045public class BytesTestBase {
046
047  private static final Logger LOG = LoggerFactory.getLogger(BytesTestBase.class);
048
049  @Test
050  public void testShort() throws Exception {
051    for (short n : Arrays.asList(Short.MIN_VALUE, (short) -100, (short) -1, (short) 0, (short) 1,
052      (short) 300, Short.MAX_VALUE)) {
053      byte[] bytes = Bytes.toBytes(n);
054      assertEquals(Bytes.toShort(bytes, 0, bytes.length), n);
055    }
056  }
057
058  @Test
059  public void testNullHashCode() {
060    byte[] b = null;
061    Exception ee = null;
062    try {
063      Bytes.hashCode(b);
064    } catch (Exception e) {
065      ee = e;
066    }
067    assertNotNull(ee);
068  }
069
070  @Test
071  public void testAdd() {
072    byte[] a = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
073    byte[] b = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
074    byte[] c = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
075    byte[] result1 = Bytes.add(a, b, c);
076    byte[] result2 = Bytes.add(new byte[][] { a, b, c });
077    assertEquals(0, Bytes.compareTo(result1, result2));
078  }
079
080  @Test
081  public void testSplit() {
082    byte[] lowest = Bytes.toBytes("AAA");
083    byte[] middle = Bytes.toBytes("CCC");
084    byte[] highest = Bytes.toBytes("EEE");
085    byte[][] parts = Bytes.split(lowest, highest, 1);
086    for (byte[] bytes : parts) {
087      LOG.info(Bytes.toString(bytes));
088    }
089    assertEquals(3, parts.length);
090    assertTrue(Bytes.equals(parts[1], middle));
091    // Now divide into three parts. Change highest so split is even.
092    highest = Bytes.toBytes("DDD");
093    parts = Bytes.split(lowest, highest, 2);
094    for (byte[] part : parts) {
095      LOG.info(Bytes.toString(part));
096    }
097    assertEquals(4, parts.length);
098    // Assert that 3rd part is 'CCC'.
099    assertTrue(Bytes.equals(parts[2], middle));
100  }
101
102  @Test
103  public void testSplit2() {
104    // More split tests.
105    byte[] lowest = Bytes.toBytes("http://A");
106    byte[] highest = Bytes.toBytes("http://z");
107    byte[] middle = Bytes.toBytes("http://]");
108    byte[][] parts = Bytes.split(lowest, highest, 1);
109    for (byte[] part : parts) {
110      LOG.info(Bytes.toString(part));
111    }
112    assertEquals(3, parts.length);
113    assertTrue(Bytes.equals(parts[1], middle));
114  }
115
116  @Test
117  public void testSplit3() {
118    // Test invalid split cases
119    byte[] low = { 1, 1, 1 };
120    byte[] high = { 1, 1, 3 };
121
122    // If swapped, should throw IAE
123    try {
124      Bytes.split(high, low, 1);
125      fail("Should not be able to split if low > high");
126    } catch (IllegalArgumentException iae) {
127      // Correct
128    }
129
130    // Single split should work
131    byte[][] parts = Bytes.split(low, high, 1);
132    for (int i = 0; i < parts.length; i++) {
133      LOG.info("" + i + " -> " + Bytes.toStringBinary(parts[i]));
134    }
135    assertEquals(3, parts.length, "Returned split should have 3 parts but has " + parts.length);
136
137    // If split more than once, use additional byte to split
138    parts = Bytes.split(low, high, 2);
139    assertNotNull(parts, "Split with an additional byte");
140    assertEquals(parts.length, low.length + 1);
141
142    // Split 0 times should throw IAE
143    try {
144      Bytes.split(low, high, 0);
145      fail("Should not be able to split 0 times");
146    } catch (IllegalArgumentException iae) {
147      // Correct
148    }
149  }
150
151  @Test
152  public void testToInt() {
153    int[] ints = { -1, 123, Integer.MIN_VALUE, Integer.MAX_VALUE };
154    for (int anInt : ints) {
155      byte[] b = Bytes.toBytes(anInt);
156      assertEquals(anInt, Bytes.toInt(b));
157      byte[] b2 = bytesWithOffset(b);
158      assertEquals(anInt, Bytes.toInt(b2, 1));
159      assertEquals(anInt, Bytes.toInt(b2, 1, Bytes.SIZEOF_INT));
160    }
161  }
162
163  @Test
164  public void testToLong() {
165    long[] longs = { -1L, 123L, Long.MIN_VALUE, Long.MAX_VALUE };
166    for (long aLong : longs) {
167      byte[] b = Bytes.toBytes(aLong);
168      assertEquals(aLong, Bytes.toLong(b));
169      byte[] b2 = bytesWithOffset(b);
170      assertEquals(aLong, Bytes.toLong(b2, 1));
171      assertEquals(aLong, Bytes.toLong(b2, 1, Bytes.SIZEOF_LONG));
172    }
173  }
174
175  @Test
176  public void testToFloat() {
177    float[] floats = { -1f, 123.123f, Float.MAX_VALUE };
178    for (float aFloat : floats) {
179      byte[] b = Bytes.toBytes(aFloat);
180      assertEquals(aFloat, Bytes.toFloat(b), 0.0f);
181      byte[] b2 = bytesWithOffset(b);
182      assertEquals(aFloat, Bytes.toFloat(b2, 1), 0.0f);
183    }
184  }
185
186  @Test
187  public void testToDouble() {
188    double[] doubles = { Double.MIN_VALUE, Double.MAX_VALUE };
189    for (double aDouble : doubles) {
190      byte[] b = Bytes.toBytes(aDouble);
191      assertEquals(aDouble, Bytes.toDouble(b), 0.0);
192      byte[] b2 = bytesWithOffset(b);
193      assertEquals(aDouble, Bytes.toDouble(b2, 1), 0.0);
194    }
195  }
196
197  @Test
198  public void testToBigDecimal() {
199    BigDecimal[] decimals =
200      { new BigDecimal("-1"), new BigDecimal("123.123"), new BigDecimal("123123123123") };
201    for (BigDecimal decimal : decimals) {
202      byte[] b = Bytes.toBytes(decimal);
203      assertEquals(decimal, Bytes.toBigDecimal(b));
204      byte[] b2 = bytesWithOffset(b);
205      assertEquals(decimal, Bytes.toBigDecimal(b2, 1, b.length));
206    }
207  }
208
209  private byte[] bytesWithOffset(byte[] src) {
210    // add one byte in front to test offset
211    byte[] result = new byte[src.length + 1];
212    result[0] = (byte) 0xAA;
213    System.arraycopy(src, 0, result, 1, src.length);
214    return result;
215  }
216
217  @Test
218  public void testToBytesForByteBuffer() {
219    byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
220    ByteBuffer target = ByteBuffer.wrap(array);
221    target.position(2);
222    target.limit(7);
223
224    byte[] actual = Bytes.toBytes(target);
225    byte[] expected = { 0, 1, 2, 3, 4, 5, 6 };
226    assertArrayEquals(expected, actual);
227    assertEquals(2, target.position());
228    assertEquals(7, target.limit());
229
230    ByteBuffer target2 = target.slice();
231    assertEquals(0, target2.position());
232    assertEquals(5, target2.limit());
233
234    byte[] actual2 = Bytes.toBytes(target2);
235    byte[] expected2 = { 2, 3, 4, 5, 6 };
236    assertArrayEquals(expected2, actual2);
237    assertEquals(0, target2.position());
238    assertEquals(5, target2.limit());
239  }
240
241  @Test
242  public void testGetBytesForByteBuffer() {
243    byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
244    ByteBuffer target = ByteBuffer.wrap(array);
245    target.position(2);
246    target.limit(7);
247
248    byte[] actual = Bytes.getBytes(target);
249    byte[] expected = { 2, 3, 4, 5, 6 };
250    assertArrayEquals(expected, actual);
251    assertEquals(2, target.position());
252    assertEquals(7, target.limit());
253  }
254
255  @Test
256  public void testReadAsVLong() throws Exception {
257    long[] longs = { -1L, 123L, Long.MIN_VALUE, Long.MAX_VALUE };
258    for (long aLong : longs) {
259      ByteArrayOutputStream baos = new ByteArrayOutputStream();
260      DataOutputStream output = new DataOutputStream(baos);
261      WritableUtils.writeVLong(output, aLong);
262      byte[] long_bytes_no_offset = baos.toByteArray();
263      assertEquals(aLong, Bytes.readAsVLong(long_bytes_no_offset, 0));
264      byte[] long_bytes_with_offset = bytesWithOffset(long_bytes_no_offset);
265      assertEquals(aLong, Bytes.readAsVLong(long_bytes_with_offset, 1));
266    }
267  }
268
269  @Test
270  public void testToStringBinaryForBytes() {
271    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
272    String actual = Bytes.toStringBinary(array);
273    String expected = "09azAZ@\\x01";
274    assertEquals(expected, actual);
275
276    String actual2 = Bytes.toStringBinary(array, 2, 3);
277    String expected2 = "azA";
278    assertEquals(expected2, actual2);
279  }
280
281  @Test
282  public void testToStringBinaryForArrayBasedByteBuffer() {
283    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
284    ByteBuffer target = ByteBuffer.wrap(array);
285    String actual = Bytes.toStringBinary(target);
286    String expected = "09azAZ@\\x01";
287    assertEquals(expected, actual);
288  }
289
290  @Test
291  public void testToStringBinaryForReadOnlyByteBuffer() {
292    byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
293    ByteBuffer target = ByteBuffer.wrap(array).asReadOnlyBuffer();
294    String actual = Bytes.toStringBinary(target);
295    String expected = "09azAZ@\\x01";
296    assertEquals(expected, actual);
297  }
298
299  @Test
300  public void testBinarySearch() {
301    byte[][] arr = { { 1 }, { 3 }, { 5 }, { 7 }, { 9 }, { 11 }, { 13 }, { 15 }, };
302    byte[] key1 = { 3, 1 };
303    byte[] key2 = { 4, 9 };
304    byte[] key2_2 = { 4 };
305    byte[] key3 = { 5, 11 };
306    byte[] key4 = { 0 };
307    byte[] key5 = { 2 };
308
309    assertEquals(1, Bytes.binarySearch(arr, key1, 0, 1));
310    assertEquals(0, Bytes.binarySearch(arr, key1, 1, 1));
311    assertEquals(-(2 + 1), Arrays.binarySearch(arr, key2_2, Bytes.BYTES_COMPARATOR));
312    assertEquals(-(2 + 1), Bytes.binarySearch(arr, key2, 0, 1));
313    assertEquals(4, Bytes.binarySearch(arr, key2, 1, 1));
314    assertEquals(2, Bytes.binarySearch(arr, key3, 0, 1));
315    assertEquals(5, Bytes.binarySearch(arr, key3, 1, 1));
316    assertEquals(-1, Bytes.binarySearch(arr, key4, 0, 1));
317    assertEquals(-2, Bytes.binarySearch(arr, key5, 0, 1));
318
319    // Search for values to the left and to the right of each item in the array.
320    for (int i = 0; i < arr.length; ++i) {
321      assertEquals(-(i + 1), Bytes.binarySearch(arr, new byte[] { (byte) (arr[i][0] - 1) }, 0, 1));
322      assertEquals(-(i + 2), Bytes.binarySearch(arr, new byte[] { (byte) (arr[i][0] + 1) }, 0, 1));
323    }
324  }
325
326  @Test
327  public void testToStringBytesBinaryReversible() {
328    byte[] randomBytes = new byte[1000];
329    for (int i = 0; i < 1000; i++) {
330      Bytes.random(randomBytes);
331      verifyReversibleForBytes(randomBytes);
332    }
333    // some specific cases
334    verifyReversibleForBytes(new byte[] {});
335    verifyReversibleForBytes(new byte[] { '\\', 'x', 'A', 'D' });
336    verifyReversibleForBytes(new byte[] { '\\', 'x', 'A', 'D', '\\' });
337  }
338
339  private void verifyReversibleForBytes(byte[] originalBytes) {
340    String convertedString = Bytes.toStringBinary(originalBytes);
341    byte[] convertedBytes = Bytes.toBytesBinary(convertedString);
342    if (Bytes.compareTo(originalBytes, convertedBytes) != 0) {
343      fail("Not reversible for\nbyte[]: " + Arrays.toString(originalBytes) + ",\nStringBinary: "
344        + convertedString);
345    }
346  }
347
348  @Test
349  public void testStartsWith() {
350    assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("h")));
351    assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("")));
352    assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("hello")));
353    assertFalse(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("helloworld")));
354    assertFalse(Bytes.startsWith(Bytes.toBytes(""), Bytes.toBytes("hello")));
355  }
356
357  @Test
358  public void testIncrementBytes() {
359    assertTrue(checkTestIncrementBytes(10, 1));
360    assertTrue(checkTestIncrementBytes(12, 123435445));
361    assertTrue(checkTestIncrementBytes(124634654, 1));
362    assertTrue(checkTestIncrementBytes(10005460, 5005645));
363    assertTrue(checkTestIncrementBytes(1, -1));
364    assertTrue(checkTestIncrementBytes(10, -1));
365    assertTrue(checkTestIncrementBytes(10, -5));
366    assertTrue(checkTestIncrementBytes(1005435000, -5));
367    assertTrue(checkTestIncrementBytes(10, -43657655));
368    assertTrue(checkTestIncrementBytes(-1, 1));
369    assertTrue(checkTestIncrementBytes(-26, 5034520));
370    assertTrue(checkTestIncrementBytes(-10657200, 5));
371    assertTrue(checkTestIncrementBytes(-12343250, 45376475));
372    assertTrue(checkTestIncrementBytes(-10, -5));
373    assertTrue(checkTestIncrementBytes(-12343250, -5));
374    assertTrue(checkTestIncrementBytes(-12, -34565445));
375    assertTrue(checkTestIncrementBytes(-1546543452, -34565445));
376  }
377
378  private static boolean checkTestIncrementBytes(long val, long amount) {
379    byte[] value = Bytes.toBytes(val);
380    byte[] testValue = { -1, -1, -1, -1, -1, -1, -1, -1 };
381    if (value[0] > 0) {
382      testValue = new byte[Bytes.SIZEOF_LONG];
383    }
384    System.arraycopy(value, 0, testValue, testValue.length - value.length, value.length);
385
386    long incrementResult = Bytes.toLong(Bytes.incrementBytes(value, amount));
387
388    return (Bytes.toLong(testValue) + amount) == incrementResult;
389  }
390
391  @Test
392  public void testFixedSizeString() throws IOException {
393    ByteArrayOutputStream baos = new ByteArrayOutputStream();
394    DataOutputStream dos = new DataOutputStream(baos);
395    Bytes.writeStringFixedSize(dos, "Hello", 5);
396    Bytes.writeStringFixedSize(dos, "World", 18);
397    Bytes.writeStringFixedSize(dos, "", 9);
398
399    try {
400      // Use a long dash which is three bytes in UTF-8. If encoding happens
401      // using ISO-8859-1, this will fail.
402      Bytes.writeStringFixedSize(dos, "Too\u2013Long", 9);
403      fail("Exception expected");
404    } catch (IOException ex) {
405      assertEquals(
406        "Trying to write 10 bytes (Too\\xE2\\x80\\x93Long) into a field of " + "length 9",
407        ex.getMessage());
408    }
409
410    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
411    DataInputStream dis = new DataInputStream(bais);
412    assertEquals("Hello", Bytes.readStringFixedSize(dis, 5));
413    assertEquals("World", Bytes.readStringFixedSize(dis, 18));
414    assertEquals("", Bytes.readStringFixedSize(dis, 9));
415  }
416
417  @Test
418  public void testCopy() {
419    byte[] bytes = Bytes.toBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
420    byte[] copy = Bytes.copy(bytes);
421    assertNotSame(bytes, copy);
422    assertTrue(Bytes.equals(bytes, copy));
423  }
424
425  @Test
426  public void testToBytesBinaryTrailingBackslashes() {
427    try {
428      Bytes.toBytesBinary("abc\\x00\\x01\\");
429    } catch (StringIndexOutOfBoundsException ex) {
430      fail("Illegal string access: " + ex.getMessage());
431    }
432  }
433
434  @Test
435  public void testToStringBinary_toBytesBinary_Reversable() {
436    String bytes = Bytes.toStringBinary(Bytes.toBytes(2.17));
437    assertEquals(2.17, Bytes.toDouble(Bytes.toBytesBinary(bytes)), 0);
438  }
439
440  @Test
441  public void testUnsignedBinarySearch() {
442    byte[] bytes = new byte[] { 0, 5, 123, 127, -128, -100, -1 };
443    assertEquals(1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) 5));
444    assertEquals(3, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) 127));
445    assertEquals(4, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) -128));
446    assertEquals(5, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) -100));
447    assertEquals(6, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) -1));
448    assertEquals(-1 - 1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) 2));
449    assertEquals(-6 - 1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte) -5));
450  }
451
452  @Test
453  public void testUnsignedIncrement() {
454    byte[] a = Bytes.toBytes(0);
455    int a2 = Bytes.toInt(Bytes.unsignedCopyAndIncrement(a), 0);
456    assertEquals(1, a2);
457
458    byte[] b = Bytes.toBytes(-1);
459    byte[] actual = Bytes.unsignedCopyAndIncrement(b);
460    assertNotSame(b, actual);
461    byte[] expected = new byte[] { 1, 0, 0, 0, 0 };
462    assertArrayEquals(expected, actual);
463
464    byte[] c = Bytes.toBytes(255);// should wrap to the next significant byte
465    int c2 = Bytes.toInt(Bytes.unsignedCopyAndIncrement(c), 0);
466    assertEquals(256, c2);
467  }
468
469  @Test
470  public void testIndexOf() {
471    byte[] array = Bytes.toBytes("hello");
472    assertEquals(1, Bytes.indexOf(array, (byte) 'e'));
473    assertEquals(4, Bytes.indexOf(array, (byte) 'o'));
474    assertEquals(-1, Bytes.indexOf(array, (byte) 'a'));
475    assertEquals(0, Bytes.indexOf(array, Bytes.toBytes("hel")));
476    assertEquals(2, Bytes.indexOf(array, Bytes.toBytes("ll")));
477    assertEquals(-1, Bytes.indexOf(array, Bytes.toBytes("hll")));
478  }
479
480  @Test
481  public void testContains() {
482    byte[] array = Bytes.toBytes("hello world");
483    assertTrue(Bytes.contains(array, (byte) 'e'));
484    assertTrue(Bytes.contains(array, (byte) 'd'));
485    assertFalse(Bytes.contains(array, (byte) 'a'));
486    assertTrue(Bytes.contains(array, Bytes.toBytes("world")));
487    assertTrue(Bytes.contains(array, Bytes.toBytes("ello")));
488    assertFalse(Bytes.contains(array, Bytes.toBytes("owo")));
489  }
490
491  @Test
492  public void testZero() {
493    byte[] array = Bytes.toBytes("hello");
494    Bytes.zero(array);
495    for (byte b : array) {
496      assertEquals(0, b);
497    }
498    array = Bytes.toBytes("hello world");
499    Bytes.zero(array, 2, 7);
500    assertFalse(array[0] == 0);
501    assertFalse(array[1] == 0);
502    for (int i = 2; i < 9; i++) {
503      assertEquals(0, array[i]);
504    }
505    for (int i = 9; i < array.length; i++) {
506      assertFalse(array[i] == 0);
507    }
508  }
509
510  @Test
511  public void testPutBuffer() {
512    byte[] b = new byte[100];
513    for (byte i = 0; i < 100; i++) {
514      Bytes.putByteBuffer(b, i, ByteBuffer.wrap(new byte[] { i }));
515    }
516    for (byte i = 0; i < 100; i++) {
517      assertEquals(i, b[i]);
518    }
519  }
520
521  @Test
522  public void testToFromHex() {
523    List<String> testStrings = new ArrayList<>(8);
524    testStrings.addAll(Arrays.asList("", "00", "A0", "ff", "FFffFFFFFFFFFF", "12",
525      "0123456789abcdef", "283462839463924623984692834692346ABCDFEDDCA0"));
526    for (String testString : testStrings) {
527      byte[] byteData = Bytes.fromHex(testString);
528      assertEquals(testString.length() / 2, byteData.length);
529      String result = Bytes.toHex(byteData);
530      assertTrue(testString.equalsIgnoreCase(result));
531    }
532
533    List<byte[]> testByteData = new ArrayList<>(5);
534    testByteData.addAll(Arrays.asList(new byte[0], new byte[1], new byte[10],
535      new byte[] { 1, 2, 3, 4, 5 }, new byte[] { (byte) 0xFF }));
536    Random rand = ThreadLocalRandom.current();
537    for (int i = 0; i < 20; i++) {
538      byte[] bytes = new byte[rand.nextInt(100)];
539      Bytes.random(bytes);
540      testByteData.add(bytes);
541    }
542
543    for (byte[] testData : testByteData) {
544      String hexString = Bytes.toHex(testData);
545      assertEquals(testData.length * 2, hexString.length());
546      byte[] result = Bytes.fromHex(hexString);
547      assertArrayEquals(testData, result);
548    }
549  }
550
551  @Test
552  public void testFindCommonPrefix() throws Exception {
553    // tests for common prefixes less than 8 bytes in length (i.e. using non-vectorized path)
554    byte[] hello = Bytes.toBytes("hello");
555    byte[] helloWorld = Bytes.toBytes("helloworld");
556
557    assertEquals(5,
558      Bytes.findCommonPrefix(hello, helloWorld, hello.length, helloWorld.length, 0, 0));
559    assertEquals(5, Bytes.findCommonPrefix(hello, hello, hello.length, hello.length, 0, 0));
560    assertEquals(3, Bytes.findCommonPrefix(hello, hello, hello.length - 2, hello.length - 2, 2, 2));
561    assertEquals(0, Bytes.findCommonPrefix(hello, hello, 0, 0, 0, 0));
562
563    // tests for common prefixes greater than 8 bytes in length which may use the vectorized path
564    byte[] hellohello = Bytes.toBytes("hellohello");
565    byte[] hellohellohi = Bytes.toBytes("hellohellohi");
566
567    assertEquals(10, Bytes.findCommonPrefix(hellohello, hellohellohi, hellohello.length,
568      hellohellohi.length, 0, 0));
569    assertEquals(10, Bytes.findCommonPrefix(hellohellohi, hellohello, hellohellohi.length,
570      hellohello.length, 0, 0));
571    assertEquals(10,
572      Bytes.findCommonPrefix(hellohello, hellohello, hellohello.length, hellohello.length, 0, 0));
573
574    hellohello[2] = 0;
575    assertEquals(2, Bytes.findCommonPrefix(hellohello, hellohellohi, hellohello.length,
576      hellohellohi.length, 0, 0));
577  }
578}