1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.util;
19
20 import static org.junit.Assert.assertArrayEquals;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.DataInputStream;
25 import java.io.DataOutputStream;
26 import java.io.IOException;
27 import java.lang.reflect.Field;
28 import java.lang.reflect.Modifier;
29 import java.math.BigDecimal;
30 import java.nio.ByteBuffer;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Random;
35
36 import junit.framework.TestCase;
37
38 import org.apache.hadoop.hbase.testclassification.SmallTests;
39 import org.apache.hadoop.io.WritableUtils;
40 import org.junit.Assert;
41 import org.junit.experimental.categories.Category;
42
43 @Category(SmallTests.class)
44 public class TestBytes extends TestCase {
45 private static void setUnsafe(boolean value) throws Exception {
46 Field field = Bytes.class.getDeclaredField("UNSAFE_UNALIGNED");
47 field.setAccessible(true);
48 Field modifiersField = Field.class.getDeclaredField("modifiers");
49 modifiersField.setAccessible(true);
50 int oldModifiers = field.getModifiers();
51 modifiersField.setInt(field, oldModifiers & ~Modifier.FINAL);
52 try {
53 field.set(null, value);
54 } finally {
55 modifiersField.setInt(field, oldModifiers);
56 }
57 assertEquals(Bytes.UNSAFE_UNALIGNED, value);
58 }
59
60 public void testShort() throws Exception {
61 testShort(false);
62 }
63
64 public void testShortUnsafe() throws Exception {
65 testShort(true);
66 }
67
68 private static void testShort(boolean unsafe) throws Exception {
69 setUnsafe(unsafe);
70 try {
71 for (short n : Arrays.asList(
72 Short.MIN_VALUE,
73 (short) -100,
74 (short) -1,
75 (short) 0,
76 (short) 1,
77 (short) 300,
78 Short.MAX_VALUE)) {
79 byte[] bytes = Bytes.toBytes(n);
80 assertEquals(Bytes.toShort(bytes, 0, bytes.length), n);
81 }
82 } finally {
83 setUnsafe(UnsafeAvailChecker.unaligned());
84 }
85 }
86
87 public void testNullHashCode() {
88 byte [] b = null;
89 Exception ee = null;
90 try {
91 Bytes.hashCode(b);
92 } catch (Exception e) {
93 ee = e;
94 }
95 assertNotNull(ee);
96 }
97
98 public void testAdd() {
99 byte[] a = {0,0,0,0,0,0,0,0,0,0};
100 byte[] b = {1,1,1,1,1,1,1,1,1,1,1};
101 byte[] c = {2,2,2,2,2,2,2,2,2,2,2,2};
102 byte[] d = {3,3,3,3,3,3,3,3,3,3,3,3,3};
103 byte[] result1 = Bytes.add(a, b, c);
104 byte[] result2 = Bytes.add(new byte[][] {a, b, c});
105 assertEquals(0, Bytes.compareTo(result1, result2));
106 byte[] result4 = Bytes.add(result1, d);
107 byte[] result5 = Bytes.add(new byte[][] {result1, d});
108 assertEquals(0, Bytes.compareTo(result1, result2));
109 }
110
111 public void testSplit() {
112 byte[] lowest = Bytes.toBytes("AAA");
113 byte[] middle = Bytes.toBytes("CCC");
114 byte[] highest = Bytes.toBytes("EEE");
115 byte[][] parts = Bytes.split(lowest, highest, 1);
116 for (byte[] bytes : parts) {
117 System.out.println(Bytes.toString(bytes));
118 }
119 assertEquals(3, parts.length);
120 assertTrue(Bytes.equals(parts[1], middle));
121
122 highest = Bytes.toBytes("DDD");
123 parts = Bytes.split(lowest, highest, 2);
124 for (byte[] part : parts) {
125 System.out.println(Bytes.toString(part));
126 }
127 assertEquals(4, parts.length);
128
129 assertTrue(Bytes.equals(parts[2], middle));
130 }
131
132 public void testSplit2() {
133
134 byte [] lowest = Bytes.toBytes("http://A");
135 byte [] highest = Bytes.toBytes("http://z");
136 byte [] middle = Bytes.toBytes("http://]");
137 byte [][] parts = Bytes.split(lowest, highest, 1);
138 for (byte[] part : parts) {
139 System.out.println(Bytes.toString(part));
140 }
141 assertEquals(3, parts.length);
142 assertTrue(Bytes.equals(parts[1], middle));
143 }
144
145 public void testSplit3() {
146
147 byte[] low = { 1, 1, 1 };
148 byte[] high = { 1, 1, 3 };
149
150
151 try {
152 Bytes.split(high, low, 1);
153 fail("Should not be able to split if low > high");
154 } catch(IllegalArgumentException iae) {
155
156 }
157
158
159 byte[][] parts = Bytes.split(low, high, 1);
160 for (int i = 0; i < parts.length; i++) {
161 System.out.println("" + i + " -> " + Bytes.toStringBinary(parts[i]));
162 }
163 assertEquals("Returned split should have 3 parts but has " + parts.length, 3, parts.length);
164
165
166 parts = Bytes.split(low, high, 2);
167 assertNotNull("Split with an additional byte", parts);
168 assertEquals(parts.length, low.length + 1);
169
170
171 try {
172 Bytes.split(low, high, 0);
173 fail("Should not be able to split 0 times");
174 } catch(IllegalArgumentException iae) {
175
176 }
177 }
178
179 public void testToInt() {
180 int[] ints = { -1, 123, Integer.MIN_VALUE, Integer.MAX_VALUE };
181 for (int anInt : ints) {
182 byte[] b = Bytes.toBytes(anInt);
183 assertEquals(anInt, Bytes.toInt(b));
184 byte[] b2 = bytesWithOffset(b);
185 assertEquals(anInt, Bytes.toInt(b2, 1));
186 assertEquals(anInt, Bytes.toInt(b2, 1, Bytes.SIZEOF_INT));
187 }
188 }
189
190 public void testToLong() {
191 long[] longs = { -1L, 123L, Long.MIN_VALUE, Long.MAX_VALUE };
192 for (long aLong : longs) {
193 byte[] b = Bytes.toBytes(aLong);
194 assertEquals(aLong, Bytes.toLong(b));
195 byte[] b2 = bytesWithOffset(b);
196 assertEquals(aLong, Bytes.toLong(b2, 1));
197 assertEquals(aLong, Bytes.toLong(b2, 1, Bytes.SIZEOF_LONG));
198 }
199 }
200
201 public void testToFloat() {
202 float[] floats = { -1f, 123.123f, Float.MAX_VALUE };
203 for (float aFloat : floats) {
204 byte[] b = Bytes.toBytes(aFloat);
205 assertEquals(aFloat, Bytes.toFloat(b), 0.0f);
206 byte[] b2 = bytesWithOffset(b);
207 assertEquals(aFloat, Bytes.toFloat(b2, 1), 0.0f);
208 }
209 }
210
211 public void testToDouble() {
212 double [] doubles = {Double.MIN_VALUE, Double.MAX_VALUE};
213 for (double aDouble : doubles) {
214 byte[] b = Bytes.toBytes(aDouble);
215 assertEquals(aDouble, Bytes.toDouble(b), 0.0);
216 byte[] b2 = bytesWithOffset(b);
217 assertEquals(aDouble, Bytes.toDouble(b2, 1), 0.0);
218 }
219 }
220
221 public void testToBigDecimal() {
222 BigDecimal[] decimals = { new BigDecimal("-1"), new BigDecimal("123.123"),
223 new BigDecimal("123123123123") };
224 for (BigDecimal decimal : decimals) {
225 byte[] b = Bytes.toBytes(decimal);
226 assertEquals(decimal, Bytes.toBigDecimal(b));
227 byte[] b2 = bytesWithOffset(b);
228 assertEquals(decimal, Bytes.toBigDecimal(b2, 1, b.length));
229 }
230 }
231
232 private byte[] bytesWithOffset(byte[] src) {
233
234 byte [] result = new byte[src.length + 1];
235 result[0] = (byte) 0xAA;
236 System.arraycopy(src, 0, result, 1, src.length);
237 return result;
238 }
239
240 public void testToBytesForByteBuffer() {
241 byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
242 ByteBuffer target = ByteBuffer.wrap(array);
243 target.position(2);
244 target.limit(7);
245
246 byte[] actual = Bytes.toBytes(target);
247 byte[] expected = { 0, 1, 2, 3, 4, 5, 6 };
248 assertArrayEquals(expected, actual);
249 assertEquals(2, target.position());
250 assertEquals(7, target.limit());
251
252 ByteBuffer target2 = target.slice();
253 assertEquals(0, target2.position());
254 assertEquals(5, target2.limit());
255
256 byte[] actual2 = Bytes.toBytes(target2);
257 byte[] expected2 = { 2, 3, 4, 5, 6 };
258 assertArrayEquals(expected2, actual2);
259 assertEquals(0, target2.position());
260 assertEquals(5, target2.limit());
261 }
262
263 public void testGetBytesForByteBuffer() {
264 byte[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
265 ByteBuffer target = ByteBuffer.wrap(array);
266 target.position(2);
267 target.limit(7);
268
269 byte[] actual = Bytes.getBytes(target);
270 byte[] expected = { 2, 3, 4, 5, 6 };
271 assertArrayEquals(expected, actual);
272 assertEquals(2, target.position());
273 assertEquals(7, target.limit());
274 }
275
276 public void testReadAsVLong() throws Exception {
277 long[] longs = { -1L, 123L, Long.MIN_VALUE, Long.MAX_VALUE };
278 for (long aLong : longs) {
279 ByteArrayOutputStream baos = new ByteArrayOutputStream();
280 DataOutputStream output = new DataOutputStream(baos);
281 WritableUtils.writeVLong(output, aLong);
282 byte[] long_bytes_no_offset = baos.toByteArray();
283 assertEquals(aLong, Bytes.readAsVLong(long_bytes_no_offset, 0));
284 byte[] long_bytes_with_offset = bytesWithOffset(long_bytes_no_offset);
285 assertEquals(aLong, Bytes.readAsVLong(long_bytes_with_offset, 1));
286 }
287 }
288
289 public void testToStringBinaryForBytes() {
290 byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
291 String actual = Bytes.toStringBinary(array);
292 String expected = "09azAZ@\\x01";
293 assertEquals(expected, actual);
294
295 String actual2 = Bytes.toStringBinary(array, 2, 3);
296 String expected2 = "azA";
297 assertEquals(expected2, actual2);
298 }
299
300 public void testToStringBinaryForArrayBasedByteBuffer() {
301 byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
302 ByteBuffer target = ByteBuffer.wrap(array);
303 String actual = Bytes.toStringBinary(target);
304 String expected = "09azAZ@\\x01";
305 assertEquals(expected, actual);
306 }
307
308 public void testToStringBinaryForReadOnlyByteBuffer() {
309 byte[] array = { '0', '9', 'a', 'z', 'A', 'Z', '@', 1 };
310 ByteBuffer target = ByteBuffer.wrap(array).asReadOnlyBuffer();
311 String actual = Bytes.toStringBinary(target);
312 String expected = "09azAZ@\\x01";
313 assertEquals(expected, actual);
314 }
315
316 public void testBinarySearch() {
317 byte[][] arr = {
318 { 1 },
319 { 3 },
320 { 5 },
321 { 7 },
322 { 9 },
323 { 11 },
324 { 13 },
325 { 15 },
326 };
327 byte[] key1 = { 3, 1 };
328 byte[] key2 = { 4, 9 };
329 byte[] key2_2 = { 4 };
330 byte[] key3 = { 5, 11 };
331 byte[] key4 = { 0 };
332 byte[] key5 = { 2 };
333
334 assertEquals(1, Bytes.binarySearch(arr, key1, 0, 1,
335 Bytes.BYTES_RAWCOMPARATOR));
336 assertEquals(0, Bytes.binarySearch(arr, key1, 1, 1,
337 Bytes.BYTES_RAWCOMPARATOR));
338 assertEquals(-(2+1), Arrays.binarySearch(arr, key2_2,
339 Bytes.BYTES_COMPARATOR));
340 assertEquals(-(2+1), Bytes.binarySearch(arr, key2, 0, 1,
341 Bytes.BYTES_RAWCOMPARATOR));
342 assertEquals(4, Bytes.binarySearch(arr, key2, 1, 1,
343 Bytes.BYTES_RAWCOMPARATOR));
344 assertEquals(2, Bytes.binarySearch(arr, key3, 0, 1,
345 Bytes.BYTES_RAWCOMPARATOR));
346 assertEquals(5, Bytes.binarySearch(arr, key3, 1, 1,
347 Bytes.BYTES_RAWCOMPARATOR));
348 assertEquals(-1,
349 Bytes.binarySearch(arr, key4, 0, 1, Bytes.BYTES_RAWCOMPARATOR));
350 assertEquals(-2,
351 Bytes.binarySearch(arr, key5, 0, 1, Bytes.BYTES_RAWCOMPARATOR));
352
353
354 for (int i = 0; i < arr.length; ++i) {
355 assertEquals(-(i + 1), Bytes.binarySearch(arr,
356 new byte[] { (byte) (arr[i][0] - 1) }, 0, 1,
357 Bytes.BYTES_RAWCOMPARATOR));
358 assertEquals(-(i + 2), Bytes.binarySearch(arr,
359 new byte[] { (byte) (arr[i][0] + 1) }, 0, 1,
360 Bytes.BYTES_RAWCOMPARATOR));
361 }
362 }
363
364 public void testToStringBytesBinaryReversible() {
365
366 Random rand = new Random(System.currentTimeMillis());
367 byte[] randomBytes = new byte[1000];
368 for (int i = 0; i < 1000; i++) {
369 rand.nextBytes(randomBytes);
370 verifyReversibleForBytes(randomBytes);
371 }
372
373
374 verifyReversibleForBytes(new byte[] {});
375 verifyReversibleForBytes(new byte[] {'\\', 'x', 'A', 'D'});
376 verifyReversibleForBytes(new byte[] {'\\', 'x', 'A', 'D', '\\'});
377 }
378
379 private void verifyReversibleForBytes(byte[] originalBytes) {
380 String convertedString = Bytes.toStringBinary(originalBytes);
381 byte[] convertedBytes = Bytes.toBytesBinary(convertedString);
382 if (Bytes.compareTo(originalBytes, convertedBytes) != 0) {
383 fail("Not reversible for\nbyte[]: " + Arrays.toString(originalBytes) +
384 ",\nStringBinary: " + convertedString);
385 }
386 }
387
388 public void testStartsWith() {
389 assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("h")));
390 assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("")));
391 assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("hello")));
392 assertFalse(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("helloworld")));
393 assertFalse(Bytes.startsWith(Bytes.toBytes(""), Bytes.toBytes("hello")));
394 }
395
396 public void testIncrementBytes() {
397 assertTrue(checkTestIncrementBytes(10, 1));
398 assertTrue(checkTestIncrementBytes(12, 123435445));
399 assertTrue(checkTestIncrementBytes(124634654, 1));
400 assertTrue(checkTestIncrementBytes(10005460, 5005645));
401 assertTrue(checkTestIncrementBytes(1, -1));
402 assertTrue(checkTestIncrementBytes(10, -1));
403 assertTrue(checkTestIncrementBytes(10, -5));
404 assertTrue(checkTestIncrementBytes(1005435000, -5));
405 assertTrue(checkTestIncrementBytes(10, -43657655));
406 assertTrue(checkTestIncrementBytes(-1, 1));
407 assertTrue(checkTestIncrementBytes(-26, 5034520));
408 assertTrue(checkTestIncrementBytes(-10657200, 5));
409 assertTrue(checkTestIncrementBytes(-12343250, 45376475));
410 assertTrue(checkTestIncrementBytes(-10, -5));
411 assertTrue(checkTestIncrementBytes(-12343250, -5));
412 assertTrue(checkTestIncrementBytes(-12, -34565445));
413 assertTrue(checkTestIncrementBytes(-1546543452, -34565445));
414 }
415
416 private static boolean checkTestIncrementBytes(long val, long amount) {
417 byte[] value = Bytes.toBytes(val);
418 byte[] testValue = { -1, -1, -1, -1, -1, -1, -1, -1 };
419 if (value[0] > 0) {
420 testValue = new byte[Bytes.SIZEOF_LONG];
421 }
422 System.arraycopy(value, 0, testValue, testValue.length - value.length,
423 value.length);
424
425 long incrementResult = Bytes.toLong(Bytes.incrementBytes(value, amount));
426
427 return (Bytes.toLong(testValue) + amount) == incrementResult;
428 }
429
430 public void testFixedSizeString() throws IOException {
431 ByteArrayOutputStream baos = new ByteArrayOutputStream();
432 DataOutputStream dos = new DataOutputStream(baos);
433 Bytes.writeStringFixedSize(dos, "Hello", 5);
434 Bytes.writeStringFixedSize(dos, "World", 18);
435 Bytes.writeStringFixedSize(dos, "", 9);
436
437 try {
438
439
440 Bytes.writeStringFixedSize(dos, "Too\u2013Long", 9);
441 fail("Exception expected");
442 } catch (IOException ex) {
443 assertEquals(
444 "Trying to write 10 bytes (Too\\xE2\\x80\\x93Long) into a field of " +
445 "length 9", ex.getMessage());
446 }
447
448 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
449 DataInputStream dis = new DataInputStream(bais);
450 assertEquals("Hello", Bytes.readStringFixedSize(dis, 5));
451 assertEquals("World", Bytes.readStringFixedSize(dis, 18));
452 assertEquals("", Bytes.readStringFixedSize(dis, 9));
453 }
454
455 public void testCopy() {
456 byte[] bytes = Bytes.toBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
457 byte[] copy = Bytes.copy(bytes);
458 assertNotSame(bytes, copy);
459 assertTrue(Bytes.equals(bytes, copy));
460 }
461
462 public void testToBytesBinaryTrailingBackslashes() {
463 try {
464 Bytes.toBytesBinary("abc\\x00\\x01\\");
465 } catch (StringIndexOutOfBoundsException ex) {
466 fail("Illegal string access: " + ex.getMessage());
467 }
468 }
469
470 public void testToStringBinary_toBytesBinary_Reversable() {
471 String bytes = Bytes.toStringBinary(Bytes.toBytes(2.17));
472 assertEquals(2.17, Bytes.toDouble(Bytes.toBytesBinary(bytes)), 0);
473 }
474
475 public void testUnsignedBinarySearch(){
476 byte[] bytes = new byte[] { 0,5,123,127,-128,-100,-1 };
477 Assert.assertEquals(1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)5));
478 Assert.assertEquals(3, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)127));
479 Assert.assertEquals(4, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)-128));
480 Assert.assertEquals(5, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)-100));
481 Assert.assertEquals(6, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)-1));
482 Assert.assertEquals(-1-1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)2));
483 Assert.assertEquals(-6-1, Bytes.unsignedBinarySearch(bytes, 0, bytes.length, (byte)-5));
484 }
485
486 public void testUnsignedIncrement(){
487 byte[] a = Bytes.toBytes(0);
488 int a2 = Bytes.toInt(Bytes.unsignedCopyAndIncrement(a), 0);
489 Assert.assertEquals(1, a2);
490
491 byte[] b = Bytes.toBytes(-1);
492 byte[] actual = Bytes.unsignedCopyAndIncrement(b);
493 Assert.assertNotSame(b, actual);
494 byte[] expected = new byte[]{1,0,0,0,0};
495 assertArrayEquals(expected, actual);
496
497 byte[] c = Bytes.toBytes(255);
498 int c2 = Bytes.toInt(Bytes.unsignedCopyAndIncrement(c), 0);
499 Assert.assertEquals(256, c2);
500 }
501
502 public void testIndexOf() {
503 byte[] array = Bytes.toBytes("hello");
504 assertEquals(1, Bytes.indexOf(array, (byte) 'e'));
505 assertEquals(4, Bytes.indexOf(array, (byte) 'o'));
506 assertEquals(-1, Bytes.indexOf(array, (byte) 'a'));
507 assertEquals(0, Bytes.indexOf(array, Bytes.toBytes("hel")));
508 assertEquals(2, Bytes.indexOf(array, Bytes.toBytes("ll")));
509 assertEquals(-1, Bytes.indexOf(array, Bytes.toBytes("hll")));
510 }
511
512 public void testContains() {
513 byte[] array = Bytes.toBytes("hello world");
514 assertTrue(Bytes.contains(array, (byte) 'e'));
515 assertTrue(Bytes.contains(array, (byte) 'd'));
516 assertFalse(Bytes.contains(array, (byte) 'a'));
517 assertTrue(Bytes.contains(array, Bytes.toBytes("world")));
518 assertTrue(Bytes.contains(array, Bytes.toBytes("ello")));
519 assertFalse(Bytes.contains(array, Bytes.toBytes("owo")));
520 }
521
522 public void testZero() {
523 byte[] array = Bytes.toBytes("hello");
524 Bytes.zero(array);
525 for (byte b : array) {
526 assertEquals(0, b);
527 }
528 array = Bytes.toBytes("hello world");
529 Bytes.zero(array, 2, 7);
530 assertFalse(array[0] == 0);
531 assertFalse(array[1] == 0);
532 for (int i = 2; i < 9; i++) {
533 assertEquals(0, array[i]);
534 }
535 for (int i = 9; i < array.length; i++) {
536 assertFalse(array[i] == 0);
537 }
538 }
539
540 public void testPutBuffer() {
541 byte[] b = new byte[100];
542 for (byte i = 0; i < 100; i++) {
543 Bytes.putByteBuffer(b, i, ByteBuffer.wrap(new byte[] { i }));
544 }
545 for (byte i = 0; i < 100; i++) {
546 Assert.assertEquals(i, b[i]);
547 }
548 }
549
550 public void testToFromHex() {
551 List<String> testStrings = new ArrayList<>();
552 testStrings.addAll(Arrays.asList("", "00", "A0", "ff", "FFffFFFFFFFFFF", "12",
553 "0123456789abcdef", "283462839463924623984692834692346ABCDFEDDCA0"));
554 for (String testString : testStrings) {
555 byte[] byteData = Bytes.fromHex(testString);
556 Assert.assertEquals(testString.length() / 2, byteData.length);
557 String result = Bytes.toHex(byteData);
558 Assert.assertTrue(testString.equalsIgnoreCase(result));
559 }
560
561 List<byte[]> testByteData = new ArrayList<>(Arrays.asList(new byte[0], new byte[1],
562 new byte[10], new byte[] { 1, 2, 3, 4, 5 }, new byte[] { (byte) 0xFF }));
563 Random r = new Random();
564 for (int i = 0; i < 20; i++) {
565 byte[] bytes = new byte[r.nextInt(100)];
566 r.nextBytes(bytes);
567 testByteData.add(bytes);
568 }
569
570 for (byte[] testData : testByteData) {
571 String hexString = Bytes.toHex(testData);
572 Assert.assertEquals(testData.length * 2, hexString.length());
573 byte[] result = Bytes.fromHex(hexString);
574 assertArrayEquals(testData, result);
575 }
576 }
577 }