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