2 * Copyright The Apache Software Foundation
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 package org
.apache
.hadoop
.hbase
.nio
;
22 import static org
.junit
.Assert
.assertEquals
;
23 import static org
.junit
.Assert
.assertFalse
;
24 import static org
.junit
.Assert
.assertNotEquals
;
25 import static org
.junit
.Assert
.assertTrue
;
26 import static org
.junit
.Assert
.fail
;
28 import java
.io
.IOException
;
29 import java
.nio
.BufferOverflowException
;
30 import java
.nio
.ByteBuffer
;
32 import org
.apache
.hadoop
.hbase
.testclassification
.MiscTests
;
33 import org
.apache
.hadoop
.hbase
.testclassification
.SmallTests
;
34 import org
.apache
.hadoop
.hbase
.util
.ByteBufferUtils
;
35 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
36 import org
.apache
.hadoop
.hbase
.util
.ObjectIntPair
;
37 import org
.junit
.Test
;
38 import org
.junit
.experimental
.categories
.Category
;
40 @Category({ MiscTests
.class, SmallTests
.class })
41 public class TestMultiByteBuff
{
44 public void testWritesAndReads() {
46 ByteBuffer bb1
= ByteBuffer
.allocate(15);
47 ByteBuffer bb2
= ByteBuffer
.allocate(15);
50 long l1
= 45L, l2
= 100L, l3
= 12345L;
54 byte[] b
= Bytes
.toBytes(l2
);
58 MultiByteBuff mbb
= new MultiByteBuff(bb1
, bb2
);
59 assertEquals(l1
, mbb
.getLong(4));
60 assertEquals(l2
, mbb
.getLong(14));
61 assertEquals(l3
, mbb
.getLong(22));
62 assertEquals(i1
, mbb
.getInt(0));
63 assertEquals(s1
, mbb
.getShort(12));
65 assertEquals(i1
, mbb
.getInt());
66 assertEquals(l1
, mbb
.getLong());
67 assertEquals(s1
, mbb
.getShort());
68 assertEquals(l2
, mbb
.getLong());
69 assertEquals(l3
, mbb
.getLong());
71 bb1
= ByteBuffer
.allocate(15);
72 bb2
= ByteBuffer
.allocate(15);
73 mbb
= new MultiByteBuff(bb1
, bb2
);
80 mbb
.position(mbb
.position() + 2);
83 fail("'Should have thrown BufferOverflowException");
84 } catch (BufferOverflowException e
) {
86 mbb
.position(mbb
.position() - 2);
89 assertEquals(b1
, mbb
.get());
90 assertEquals(l1
, mbb
.getLong());
91 assertEquals(i1
, mbb
.getInt());
92 assertEquals(l2
, mbb
.getLong());
93 assertEquals(b2
, mbb
.get());
94 assertEquals(l3
, mbb
.getLong());
97 assertEquals(b1
, mbb
.get());
99 assertEquals(l2
, mbb
.getLong(22));
103 public void testPutPrimitives() {
104 ByteBuffer bb
= ByteBuffer
.allocate(10);
105 SingleByteBuff s
= new SingleByteBuff(bb
);
106 s
.putLong(-4465109508325701663L);
108 long long1
= bb
.getLong();
109 assertEquals(-4465109508325701663L, long1
);
114 public void testArrayBasedMethods() {
115 byte[] b
= new byte[15];
116 ByteBuffer bb1
= ByteBuffer
.wrap(b
, 1, 10).slice();
117 ByteBuffer bb2
= ByteBuffer
.allocate(15);
118 ByteBuff mbb1
= new MultiByteBuff(bb1
, bb2
);
119 assertFalse(mbb1
.hasArray());
123 } catch (UnsupportedOperationException e
) {
128 } catch (UnsupportedOperationException e
) {
130 mbb1
= new SingleByteBuff(bb1
);
131 assertTrue(mbb1
.hasArray());
132 assertEquals(1, mbb1
.arrayOffset());
133 assertEquals(b
, mbb1
.array());
134 mbb1
= new SingleByteBuff(ByteBuffer
.allocateDirect(10));
135 assertFalse(mbb1
.hasArray());
139 } catch (UnsupportedOperationException e
) {
144 } catch (UnsupportedOperationException e
) {
149 public void testMarkAndResetWithMBB() {
150 ByteBuffer bb1
= ByteBuffer
.allocateDirect(15);
151 ByteBuffer bb2
= ByteBuffer
.allocateDirect(15);
153 long l1
= 45L, l2
= 100L, l3
= 12345L;
155 bb1
.putShort((short) 2);
156 byte[] b
= Bytes
.toBytes(l2
);
160 ByteBuff multi
= new MultiByteBuff(bb1
, bb2
);
161 assertEquals(4, multi
.getInt());
162 assertEquals(l1
, multi
.getLong());
164 assertEquals((short) 2, multi
.getShort());
166 assertEquals((short) 2, multi
.getShort());
168 assertEquals(l2
, multi
.getLong());
170 assertEquals(l2
, multi
.getLong());
172 assertEquals(l3
, multi
.getLong());
174 assertEquals(l3
, multi
.getLong());
175 // Try absolute gets with mark and reset
177 assertEquals(l2
, multi
.getLong(14));
179 assertEquals(l3
, multi
.getLong(22));
180 // Just reset to see what happens
182 assertEquals(l2
, multi
.getLong(14));
184 assertEquals(l3
, multi
.getLong(22));
189 public void testSkipNBytes() {
190 ByteBuffer bb1
= ByteBuffer
.allocate(15);
191 ByteBuffer bb2
= ByteBuffer
.allocate(15);
193 long l1
= 45L, l2
= 100L, l3
= 12345L;
195 bb1
.putShort((short) 2);
196 byte[] b
= Bytes
.toBytes(l2
);
200 MultiByteBuff multi
= new MultiByteBuff(bb1
, bb2
);
201 assertEquals(4, multi
.getInt());
202 assertEquals(l1
, multi
.getLong());
204 assertEquals(l3
, multi
.getLong());
208 public void testMoveBack() {
209 ByteBuffer bb1
= ByteBuffer
.allocate(15);
210 ByteBuffer bb2
= ByteBuffer
.allocate(15);
212 long l1
= 45L, l2
= 100L, l3
= 12345L;
214 bb1
.putShort((short) 2);
215 byte[] b
= Bytes
.toBytes(l2
);
219 MultiByteBuff multi
= new MultiByteBuff(bb1
, bb2
);
220 assertEquals(4, multi
.getInt());
221 assertEquals(l1
, multi
.getLong());
226 assertEquals(l1
, multi
.getLong());
230 public void testSubBuffer() {
231 ByteBuffer bb1
= ByteBuffer
.allocateDirect(10);
232 ByteBuffer bb2
= ByteBuffer
.allocateDirect(10);
233 MultiByteBuff multi
= new MultiByteBuff(bb1
, bb2
);
234 long l1
= 1234L, l2
= 100L;
238 ByteBuffer sub
= multi
.asSubByteBuffer(Bytes
.SIZEOF_LONG
);
239 assertEquals(bb1
, sub
);
240 assertEquals(l1
, ByteBufferUtils
.toLong(sub
, sub
.position()));
241 multi
.skip(Bytes
.SIZEOF_LONG
);
242 sub
= multi
.asSubByteBuffer(Bytes
.SIZEOF_LONG
);
243 assertNotEquals(bb1
, sub
);
244 assertNotEquals(bb2
, sub
);
245 assertEquals(l2
, ByteBufferUtils
.toLong(sub
, sub
.position()));
247 ObjectIntPair
<ByteBuffer
> p
= new ObjectIntPair
<>();
248 multi
.asSubByteBuffer(8, Bytes
.SIZEOF_LONG
, p
);
249 assertNotEquals(bb1
, p
.getFirst());
250 assertNotEquals(bb2
, p
.getFirst());
251 assertEquals(0, p
.getSecond());
252 assertEquals(l2
, ByteBufferUtils
.toLong(sub
, p
.getSecond()));
256 public void testSliceDuplicateMethods() throws Exception
{
257 ByteBuffer bb1
= ByteBuffer
.allocateDirect(10);
258 ByteBuffer bb2
= ByteBuffer
.allocateDirect(15);
259 MultiByteBuff multi
= new MultiByteBuff(bb1
, bb2
);
260 long l1
= 1234L, l2
= 100L;
266 multi
.limit(multi
.position() + (2 * Bytes
.SIZEOF_LONG
));
267 MultiByteBuff sliced
= multi
.slice();
268 assertEquals(0, sliced
.position());
269 assertEquals((2 * Bytes
.SIZEOF_LONG
), sliced
.limit());
270 assertEquals(l1
, sliced
.getLong());
271 assertEquals(l2
, sliced
.getLong());
272 MultiByteBuff dup
= multi
.duplicate();
273 assertEquals(1, dup
.position());
274 assertEquals(dup
.position() + (2 * Bytes
.SIZEOF_LONG
), dup
.limit());
275 assertEquals(l1
, dup
.getLong());
276 assertEquals(l2
, dup
.getLong());
280 public void testGetWithPosOnMultiBuffers() throws IOException
{
281 byte[] b
= new byte[4];
282 byte[] b1
= new byte[4];
283 ByteBuffer bb1
= ByteBuffer
.wrap(b
);
284 ByteBuffer bb2
= ByteBuffer
.wrap(b1
);
285 MultiByteBuff mbb1
= new MultiByteBuff(bb1
, bb2
);
288 int res
= mbb1
.getInt(2);
289 byte[] bres
= new byte[4];
290 bres
[0] = mbb1
.get(2);
291 bres
[1] = mbb1
.get(3);
292 bres
[2] = mbb1
.get(4);
293 bres
[3] = mbb1
.get(5);
294 int expected
= Bytes
.toInt(bres
);
295 assertEquals(expected
, res
);
299 public void testGetIntStrictlyForwardWithPosOnMultiBuffers() throws IOException
{
300 byte[] b
= new byte[4];
301 byte[] b1
= new byte[8];
302 ByteBuffer bb1
= ByteBuffer
.wrap(b
);
303 ByteBuffer bb2
= ByteBuffer
.wrap(b1
);
304 MultiByteBuff mbb1
= new MultiByteBuff(bb1
, bb2
);
311 mbb1
.getIntAfterPosition(4);
312 byte res
= mbb1
.get(7);
313 assertEquals((byte) 2, res
);
315 int intRes
= mbb1
.getIntAfterPosition(1);
316 assertEquals(3, intRes
);
320 public void testPositonalCopyToByteArray() throws Exception
{
321 byte[] b
= new byte[4];
322 byte[] b1
= new byte[8];
323 ByteBuffer bb1
= ByteBuffer
.wrap(b
);
324 ByteBuffer bb2
= ByteBuffer
.wrap(b1
);
325 MultiByteBuff mbb1
= new MultiByteBuff(bb1
, bb2
);
331 byte[] dst
= new byte[4];
332 mbb1
.get(2, dst
, 0, 4);
333 assertEquals(4, Bytes
.toInt(dst
));
334 assertEquals(12, mbb1
.position());
337 mbb1
.get(8, dst
, 0, 4);
338 assertEquals(3, Bytes
.toInt(dst
));
339 assertEquals(1, mbb1
.position());
342 mbb1
.get(7, dst
, 0, 1);
343 assertEquals(2, dst
[0]);
344 assertEquals(12, mbb1
.position());
348 public void testToBytes() throws Exception
{
349 byte[] b
= new byte[4];
350 byte[] b1
= new byte[8];
351 for (int i
= 0; i
< b
.length
; i
++) {
354 for (int i
= 0; i
< b1
.length
; i
++) {
355 b1
[i
] = (byte) (b1
.length
+ i
);
357 ByteBuffer bb1
= ByteBuffer
.wrap(b
);
358 ByteBuffer bb2
= ByteBuffer
.wrap(b1
);
359 MultiByteBuff mbb1
= new MultiByteBuff(bb1
, bb2
);
361 // Test 1 Offset hitting exclusive second element
362 byte[] actual
= mbb1
.toBytes(6, 4);
363 assertTrue(Bytes
.equals(actual
, 0, actual
.length
,
365 // Test 2 offset hitting exclusive second element
366 // but continuing to the end of the second one
367 actual
= mbb1
.toBytes(5, 7);
368 assertTrue(Bytes
.equals(actual
, 0, actual
.length
,
370 // Test 3 with offset hitting in first element,
371 // continuing to next
372 actual
= mbb1
.toBytes(2, 7);
373 byte[] expected
= new byte[7];
374 System
.arraycopy(b
, 2, expected
, 0, 2);
375 System
.arraycopy(b1
, 0, expected
, 2, 5);
376 assertTrue(Bytes
.equals(actual
, expected
));
377 // Test 4 hitting only in first exclusively
378 actual
= mbb1
.toBytes(1, 3);
379 assertTrue(Bytes
.equals(actual
, 0, actual
.length
,
384 public void testHasRemaining() {
385 ByteBuffer b1
= ByteBuffer
.allocate(8);
386 ByteBuffer b2
= ByteBuffer
.allocate(8);
387 ByteBuffer b3
= ByteBuffer
.allocate(8);
388 MultiByteBuff mbb1
= new MultiByteBuff(b1
, b2
, b3
);
389 assertTrue(mbb1
.hasRemaining());
390 mbb1
.limit(20); // Limit in mid of last of BB
392 mbb1
.get();// We are at the end of second BB
393 assertTrue(mbb1
.hasRemaining());
395 assertFalse(mbb1
.hasRemaining());
396 mbb1
.limit(12); // Limit in mid of second BB
398 assertTrue(mbb1
.hasRemaining());
399 mbb1
.get(); // Now we have reached the limit
400 assertFalse(mbb1
.hasRemaining());
401 mbb1
.limit(16);// Limit at begin of the last BB
403 assertTrue(mbb1
.hasRemaining());
404 mbb1
.get(); // Now we have reached the limit
405 assertFalse(mbb1
.hasRemaining());