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