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.nio;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertFalse;
022import static org.junit.jupiter.api.Assertions.assertNotEquals;
023import static org.junit.jupiter.api.Assertions.assertTrue;
024import static org.junit.jupiter.api.Assertions.fail;
025
026import java.io.IOException;
027import java.nio.BufferOverflowException;
028import java.nio.BufferUnderflowException;
029import java.nio.ByteBuffer;
030import org.apache.hadoop.hbase.testclassification.MiscTests;
031import org.apache.hadoop.hbase.testclassification.SmallTests;
032import org.apache.hadoop.hbase.util.ByteBufferUtils;
033import org.apache.hadoop.hbase.util.Bytes;
034import org.apache.hadoop.hbase.util.ObjectIntPair;
035import org.junit.jupiter.api.Tag;
036import org.junit.jupiter.api.Test;
037
038@Tag(MiscTests.TAG)
039@Tag(SmallTests.TAG)
040public class TestMultiByteBuff {
041
042  /**
043   * Test right answer though we span many sub-buffers.
044   */
045  @Test
046  public void testGetShort() {
047    ByteBuffer bb1 = ByteBuffer.allocate(1);
048    bb1.put((byte) 1);
049    ByteBuffer bb2 = ByteBuffer.allocate(1);
050    bb2.put((byte) 0);
051    ByteBuffer bb3 = ByteBuffer.allocate(1);
052    bb3.put((byte) 2);
053    ByteBuffer bb4 = ByteBuffer.allocate(1);
054    bb4.put((byte) 3);
055    MultiByteBuff mbb = new MultiByteBuff(bb1, bb2, bb3, bb4);
056    assertEquals(256, mbb.getShortAfterPosition(0));
057    assertEquals(2, mbb.getShortAfterPosition(1));
058    assertEquals(515, mbb.getShortAfterPosition(2));
059  }
060
061  @Test
062  public void testWritesAndReads() {
063    // Absolute reads
064    ByteBuffer bb1 = ByteBuffer.allocate(15);
065    ByteBuffer bb2 = ByteBuffer.allocate(15);
066    int i1 = 4;
067    bb1.putInt(i1);
068    long l1 = 45L, l2 = 100L, l3 = 12345L;
069    bb1.putLong(l1);
070    short s1 = 2;
071    bb1.putShort(s1);
072    byte[] b = Bytes.toBytes(l2);
073    bb1.put(b, 0, 1);
074    bb2.put(b, 1, 7);
075    bb2.putLong(l3);
076    MultiByteBuff mbb = new MultiByteBuff(bb1, bb2);
077    assertEquals(l1, mbb.getLong(4));
078    assertEquals(l2, mbb.getLong(14));
079    assertEquals(l3, mbb.getLong(22));
080    assertEquals(i1, mbb.getInt(0));
081    assertEquals(s1, mbb.getShort(12));
082    // Relative reads
083    assertEquals(i1, mbb.getInt());
084    assertEquals(l1, mbb.getLong());
085    assertEquals(s1, mbb.getShort());
086    assertEquals(l2, mbb.getLong());
087    assertEquals(l3, mbb.getLong());
088    // Absolute writes
089    bb1 = ByteBuffer.allocate(15);
090    bb2 = ByteBuffer.allocate(15);
091    mbb = new MultiByteBuff(bb1, bb2);
092    byte b1 = 5, b2 = 31;
093    mbb.put(b1);
094    mbb.putLong(l1);
095    mbb.putInt(i1);
096    mbb.putLong(l2);
097    mbb.put(b2);
098    mbb.position(mbb.position() + 2);
099    try {
100      mbb.putLong(l3);
101      fail("'Should have thrown BufferOverflowException");
102    } catch (BufferOverflowException e) {
103    }
104    mbb.position(mbb.position() - 2);
105    mbb.putLong(l3);
106    mbb.rewind();
107    assertEquals(b1, mbb.get());
108    assertEquals(l1, mbb.getLong());
109    assertEquals(i1, mbb.getInt());
110    assertEquals(l2, mbb.getLong());
111    assertEquals(b2, mbb.get());
112    assertEquals(l3, mbb.getLong());
113    mbb.put(21, b1);
114    mbb.position(21);
115    assertEquals(b1, mbb.get());
116    mbb.put(b);
117    assertEquals(l2, mbb.getLong(22));
118  }
119
120  @Test
121  public void testPutPrimitives() {
122    ByteBuffer bb = ByteBuffer.allocate(10);
123    SingleByteBuff s = new SingleByteBuff(bb);
124    s.putLong(-4465109508325701663L);
125    bb.rewind();
126    long long1 = bb.getLong();
127    assertEquals(-4465109508325701663L, long1);
128    s.position(8);
129  }
130
131  @Test
132  public void testArrayBasedMethods() {
133    byte[] b = new byte[15];
134    ByteBuffer bb1 = ByteBuffer.wrap(b, 1, 10).slice();
135    ByteBuffer bb2 = ByteBuffer.allocate(15);
136    ByteBuff mbb1 = new MultiByteBuff(bb1, bb2);
137    assertFalse(mbb1.hasArray());
138    try {
139      mbb1.array();
140      fail();
141    } catch (UnsupportedOperationException e) {
142    }
143    try {
144      mbb1.arrayOffset();
145      fail();
146    } catch (UnsupportedOperationException e) {
147    }
148    mbb1 = new SingleByteBuff(bb1);
149    assertTrue(mbb1.hasArray());
150    assertEquals(1, mbb1.arrayOffset());
151    assertEquals(b, mbb1.array());
152    mbb1 = new SingleByteBuff(ByteBuffer.allocateDirect(10));
153    assertFalse(mbb1.hasArray());
154    try {
155      mbb1.array();
156      fail();
157    } catch (UnsupportedOperationException e) {
158    }
159    try {
160      mbb1.arrayOffset();
161      fail();
162    } catch (UnsupportedOperationException e) {
163    }
164  }
165
166  @Test
167  public void testMarkAndResetWithMBB() {
168    ByteBuffer bb1 = ByteBuffer.allocateDirect(15);
169    ByteBuffer bb2 = ByteBuffer.allocateDirect(15);
170    bb1.putInt(4);
171    long l1 = 45L, l2 = 100L, l3 = 12345L;
172    bb1.putLong(l1);
173    bb1.putShort((short) 2);
174    byte[] b = Bytes.toBytes(l2);
175    bb1.put(b, 0, 1);
176    bb2.put(b, 1, 7);
177    bb2.putLong(l3);
178    ByteBuff multi = new MultiByteBuff(bb1, bb2);
179    assertEquals(4, multi.getInt());
180    assertEquals(l1, multi.getLong());
181    multi.mark();
182    assertEquals((short) 2, multi.getShort());
183    multi.reset();
184    assertEquals((short) 2, multi.getShort());
185    multi.mark();
186    assertEquals(l2, multi.getLong());
187    multi.reset();
188    assertEquals(l2, multi.getLong());
189    multi.mark();
190    assertEquals(l3, multi.getLong());
191    multi.reset();
192    assertEquals(l3, multi.getLong());
193    // Try absolute gets with mark and reset
194    multi.mark();
195    assertEquals(l2, multi.getLong(14));
196    multi.reset();
197    assertEquals(l3, multi.getLong(22));
198    // Just reset to see what happens
199    multi.reset();
200    assertEquals(l2, multi.getLong(14));
201    multi.mark();
202    assertEquals(l3, multi.getLong(22));
203    multi.reset();
204  }
205
206  @Test
207  public void testSkipNBytes() {
208    ByteBuffer bb1 = ByteBuffer.allocate(15);
209    ByteBuffer bb2 = ByteBuffer.allocate(15);
210    bb1.putInt(4);
211    long l1 = 45L, l2 = 100L, l3 = 12345L;
212    bb1.putLong(l1);
213    bb1.putShort((short) 2);
214    byte[] b = Bytes.toBytes(l2);
215    bb1.put(b, 0, 1);
216    bb2.put(b, 1, 7);
217    bb2.putLong(l3);
218    MultiByteBuff multi = new MultiByteBuff(bb1, bb2);
219    assertEquals(4, multi.getInt());
220    assertEquals(l1, multi.getLong());
221    multi.skip(10);
222    assertEquals(l3, multi.getLong());
223  }
224
225  @Test
226  public void testMoveBack() {
227    ByteBuffer bb1 = ByteBuffer.allocate(15);
228    ByteBuffer bb2 = ByteBuffer.allocate(15);
229    bb1.putInt(4);
230    long l1 = 45L, l2 = 100L, l3 = 12345L;
231    bb1.putLong(l1);
232    bb1.putShort((short) 2);
233    byte[] b = Bytes.toBytes(l2);
234    bb1.put(b, 0, 1);
235    bb2.put(b, 1, 7);
236    bb2.putLong(l3);
237    MultiByteBuff multi = new MultiByteBuff(bb1, bb2);
238    assertEquals(4, multi.getInt());
239    assertEquals(l1, multi.getLong());
240    multi.skip(10);
241    multi.moveBack(4);
242    multi.moveBack(6);
243    multi.moveBack(8);
244    assertEquals(l1, multi.getLong());
245  }
246
247  @Test
248  public void testSubBuffer() {
249    ByteBuffer bb1 = ByteBuffer.allocateDirect(10);
250    ByteBuffer bb2 = ByteBuffer.allocateDirect(10);
251    MultiByteBuff multi = new MultiByteBuff(bb1, bb2);
252    long l1 = 1234L, l2 = 100L;
253    multi.putLong(l1);
254    multi.putLong(l2);
255    multi.rewind();
256    ByteBuffer sub = multi.asSubByteBuffer(Bytes.SIZEOF_LONG);
257    assertEquals(bb1, sub);
258    assertEquals(l1, ByteBufferUtils.toLong(sub, sub.position()));
259    multi.skip(Bytes.SIZEOF_LONG);
260    sub = multi.asSubByteBuffer(Bytes.SIZEOF_LONG);
261    assertNotEquals(bb1, sub);
262    assertNotEquals(bb2, sub);
263    assertEquals(l2, ByteBufferUtils.toLong(sub, sub.position()));
264    multi.rewind();
265    ObjectIntPair<ByteBuffer> p = new ObjectIntPair<>();
266    multi.asSubByteBuffer(8, Bytes.SIZEOF_LONG, p);
267    assertNotEquals(bb1, p.getFirst());
268    assertNotEquals(bb2, p.getFirst());
269    assertEquals(0, p.getSecond());
270    assertEquals(l2, ByteBufferUtils.toLong(sub, p.getSecond()));
271  }
272
273  @Test
274  public void testSliceDuplicateMethods() throws Exception {
275    ByteBuffer bb1 = ByteBuffer.allocateDirect(10);
276    ByteBuffer bb2 = ByteBuffer.allocateDirect(15);
277    MultiByteBuff multi = new MultiByteBuff(bb1, bb2);
278    long l1 = 1234L, l2 = 100L;
279    multi.put((byte) 2);
280    multi.putLong(l1);
281    multi.putLong(l2);
282    multi.putInt(45);
283    multi.position(1);
284    multi.limit(multi.position() + (2 * Bytes.SIZEOF_LONG));
285    ByteBuff sliced = multi.slice();
286    assertEquals(0, sliced.position());
287    assertEquals((2 * Bytes.SIZEOF_LONG), sliced.limit());
288    assertEquals(l1, sliced.getLong());
289    assertEquals(l2, sliced.getLong());
290    ByteBuff dup = multi.duplicate();
291    assertEquals(1, dup.position());
292    assertEquals(dup.position() + (2 * Bytes.SIZEOF_LONG), dup.limit());
293    assertEquals(l1, dup.getLong());
294    assertEquals(l2, dup.getLong());
295  }
296
297  @Test
298  public void testGetWithPosOnMultiBuffers() throws IOException {
299    byte[] b = new byte[4];
300    byte[] b1 = new byte[4];
301    ByteBuffer bb1 = ByteBuffer.wrap(b);
302    ByteBuffer bb2 = ByteBuffer.wrap(b1);
303    MultiByteBuff mbb1 = new MultiByteBuff(bb1, bb2);
304    mbb1.position(2);
305    mbb1.putInt(4);
306    int res = mbb1.getInt(2);
307    byte[] bres = new byte[4];
308    bres[0] = mbb1.get(2);
309    bres[1] = mbb1.get(3);
310    bres[2] = mbb1.get(4);
311    bres[3] = mbb1.get(5);
312    int expected = Bytes.toInt(bres);
313    assertEquals(expected, res);
314  }
315
316  @Test
317  public void testGetIntStrictlyForwardWithPosOnMultiBuffers() throws IOException {
318    byte[] b = new byte[4];
319    byte[] b1 = new byte[8];
320    ByteBuffer bb1 = ByteBuffer.wrap(b);
321    ByteBuffer bb2 = ByteBuffer.wrap(b1);
322    MultiByteBuff mbb1 = new MultiByteBuff(bb1, bb2);
323    mbb1.position(2);
324    mbb1.putInt(4);
325    mbb1.position(7);
326    mbb1.put((byte) 2);
327    mbb1.putInt(3);
328    mbb1.rewind();
329    mbb1.getIntAfterPosition(4);
330    byte res = mbb1.get(7);
331    assertEquals((byte) 2, res);
332    mbb1.position(7);
333    int intRes = mbb1.getIntAfterPosition(1);
334    assertEquals(3, intRes);
335  }
336
337  @Test
338  public void testPositonalCopyToByteArray() throws Exception {
339    byte[] b = new byte[4];
340    byte[] b1 = new byte[8];
341    ByteBuffer bb1 = ByteBuffer.wrap(b);
342    ByteBuffer bb2 = ByteBuffer.wrap(b1);
343    MultiByteBuff mbb1 = new MultiByteBuff(bb1, bb2);
344    mbb1.position(2);
345    mbb1.putInt(4);
346    mbb1.position(7);
347    mbb1.put((byte) 2);
348    mbb1.putInt(3);
349    byte[] dst = new byte[4];
350    mbb1.get(2, dst, 0, 4);
351    assertEquals(4, Bytes.toInt(dst));
352    assertEquals(12, mbb1.position());
353    mbb1.position(1);
354    dst = new byte[4];
355    mbb1.get(8, dst, 0, 4);
356    assertEquals(3, Bytes.toInt(dst));
357    assertEquals(1, mbb1.position());
358    mbb1.position(12);
359    dst = new byte[1];
360    mbb1.get(7, dst, 0, 1);
361    assertEquals(2, dst[0]);
362    assertEquals(12, mbb1.position());
363  }
364
365  @Test
366  public void testToBytes() throws Exception {
367    byte[] b = new byte[4];
368    byte[] b1 = new byte[8];
369    for (int i = 0; i < b.length; i++) {
370      b[i] = (byte) i;
371    }
372    for (int i = 0; i < b1.length; i++) {
373      b1[i] = (byte) (b1.length + i);
374    }
375    ByteBuffer bb1 = ByteBuffer.wrap(b);
376    ByteBuffer bb2 = ByteBuffer.wrap(b1);
377    MultiByteBuff mbb1 = new MultiByteBuff(bb1, bb2);
378
379    // Test 1 Offset hitting exclusive second element
380    byte[] actual = mbb1.toBytes(6, 4);
381    assertTrue(Bytes.equals(actual, 0, actual.length, b1, 2, 4));
382    // Test 2 offset hitting exclusive second element
383    // but continuing to the end of the second one
384    actual = mbb1.toBytes(5, 7);
385    assertTrue(Bytes.equals(actual, 0, actual.length, b1, 1, 7));
386    // Test 3 with offset hitting in first element,
387    // continuing to next
388    actual = mbb1.toBytes(2, 7);
389    byte[] expected = new byte[7];
390    System.arraycopy(b, 2, expected, 0, 2);
391    System.arraycopy(b1, 0, expected, 2, 5);
392    assertTrue(Bytes.equals(actual, expected));
393    // Test 4 hitting only in first exclusively
394    actual = mbb1.toBytes(1, 3);
395    assertTrue(Bytes.equals(actual, 0, actual.length, b, 1, 3));
396  }
397
398  @Test
399  public void testHasRemaining() {
400    ByteBuffer b1 = ByteBuffer.allocate(8);
401    ByteBuffer b2 = ByteBuffer.allocate(8);
402    ByteBuffer b3 = ByteBuffer.allocate(8);
403    MultiByteBuff mbb1 = new MultiByteBuff(b1, b2, b3);
404    assertTrue(mbb1.hasRemaining());
405    mbb1.limit(20); // Limit in mid of last of BB
406    mbb1.position(15);
407    mbb1.get();// We are at the end of second BB
408    assertTrue(mbb1.hasRemaining());
409    mbb1.position(20);
410    assertFalse(mbb1.hasRemaining());
411    mbb1.limit(12); // Limit in mid of second BB
412    mbb1.position(11);
413    assertTrue(mbb1.hasRemaining());
414    mbb1.get(); // Now we have reached the limit
415    assertFalse(mbb1.hasRemaining());
416    mbb1.limit(16);// Limit at begin of the last BB
417    mbb1.position(15);
418    assertTrue(mbb1.hasRemaining());
419    mbb1.get(); // Now we have reached the limit
420    assertFalse(mbb1.hasRemaining());
421  }
422
423  @Test
424  public void testGetPrimitivesWithSmallIndividualBBs() {
425    short s = 45;
426    int i = 2345;
427    long l = 75681526L;
428    ByteBuffer bb = ByteBuffer.allocate(14);
429    bb.putShort(s);
430    bb.putInt(i);
431    bb.putLong(l);
432
433    ByteBuffer bb1 = ((ByteBuffer) bb.duplicate().position(0).limit(1)).slice();
434    ByteBuffer bb2 = ((ByteBuffer) bb.duplicate().position(1).limit(3)).slice();
435    ByteBuffer bb3 = ((ByteBuffer) bb.duplicate().position(3).limit(5)).slice();
436    ByteBuffer bb4 = ((ByteBuffer) bb.duplicate().position(5).limit(11)).slice();
437    ByteBuffer bb5 = ((ByteBuffer) bb.duplicate().position(11).limit(12)).slice();
438    ByteBuffer bb6 = ((ByteBuffer) bb.duplicate().position(12).limit(14)).slice();
439    MultiByteBuff mbb = new MultiByteBuff(bb1, bb2, bb3, bb4, bb5, bb6);
440    assertEquals(s, mbb.getShortAfterPosition(0));
441    assertEquals(i, mbb.getIntAfterPosition(2));
442    assertEquals(l, mbb.getLongAfterPosition(6));
443
444    assertEquals(s, mbb.getShort(0));
445    assertEquals(i, mbb.getInt(2));
446    assertEquals(l, mbb.getLong(6));
447
448    mbb.position(0);
449    assertEquals(s, mbb.getShort());
450    assertEquals(i, mbb.getInt());
451    assertEquals(l, mbb.getLong());
452  }
453
454  @Test
455  public void testGetByteBufferWithOffsetAndPos() {
456    byte[] a = Bytes.toBytes("abcd");
457    byte[] b = Bytes.toBytes("efghijkl");
458    ByteBuffer aa = ByteBuffer.wrap(a);
459    ByteBuffer bb = ByteBuffer.wrap(b);
460    MultiByteBuff mbb = new MultiByteBuff(aa, bb);
461    ByteBuffer out = ByteBuffer.allocate(12);
462    mbb.get(out, 0, 1);
463    assertEquals(out.position(), 1);
464    assertTrue(Bytes.equals(Bytes.toBytes("a"), 0, 1, out.array(), 0, 1));
465
466    mbb.get(out, 1, 4);
467    assertEquals(out.position(), 5);
468    assertTrue(Bytes.equals(Bytes.toBytes("abcde"), 0, 5, out.array(), 0, 5));
469
470    mbb.get(out, 10, 1);
471    assertEquals(out.position(), 6);
472    assertTrue(Bytes.equals(Bytes.toBytes("abcdek"), 0, 6, out.array(), 0, 6));
473
474    mbb.get(out, 0, 6);
475    assertEquals(out.position(), 12);
476    assertTrue(Bytes.equals(Bytes.toBytes("abcdekabcdef"), 0, 12, out.array(), 0, 12));
477  }
478
479  @Test
480  public void testPositionalPutByteBuff() throws Exception {
481    ByteBuffer bb1 = ByteBuffer.allocate(100);
482    ByteBuffer bb2 = ByteBuffer.allocate(100);
483    MultiByteBuff srcMultiByteBuff = new MultiByteBuff(bb1, bb2);
484    for (int i = 0; i < 25; i++) {
485      srcMultiByteBuff.putLong(i * 8L);
486    }
487    // Test MultiByteBuff To MultiByteBuff
488    doTestPositionalPutByteBuff(srcMultiByteBuff);
489
490    ByteBuffer bb3 = ByteBuffer.allocate(200);
491    SingleByteBuff srcSingleByteBuff = new SingleByteBuff(bb3);
492    for (int i = 0; i < 25; i++) {
493      srcSingleByteBuff.putLong(i * 8L);
494    }
495    // Test SingleByteBuff To MultiByteBuff
496    doTestPositionalPutByteBuff(srcSingleByteBuff);
497  }
498
499  private void doTestPositionalPutByteBuff(ByteBuff srcByteBuff) throws Exception {
500    ByteBuffer bb3 = ByteBuffer.allocate(50);
501    ByteBuffer bb4 = ByteBuffer.allocate(50);
502    ByteBuffer bb5 = ByteBuffer.allocate(50);
503    ByteBuffer bb6 = ByteBuffer.allocate(50);
504    MultiByteBuff destMultiByteBuff = new MultiByteBuff(bb3, bb4, bb5, bb6);
505
506    // full copy
507    destMultiByteBuff.put(0, srcByteBuff, 0, 200);
508    int compareTo = ByteBuff.compareTo(srcByteBuff, 0, 200, destMultiByteBuff, 0, 200);
509    assertTrue(compareTo == 0);
510
511    // Test src to dest first ByteBuffer
512    destMultiByteBuff.put(0, srcByteBuff, 32, 63);
513    compareTo = ByteBuff.compareTo(srcByteBuff, 32, 63, destMultiByteBuff, 0, 63);
514    assertTrue(compareTo == 0);
515
516    // Test src to dest first and second ByteBuffer
517    destMultiByteBuff.put(0, srcByteBuff, 0, 63);
518    compareTo = ByteBuff.compareTo(srcByteBuff, 0, 63, destMultiByteBuff, 0, 63);
519    assertTrue(compareTo == 0);
520
521    // Test src to dest third ByteBuffer
522    destMultiByteBuff.put(100, srcByteBuff, 100, 50);
523    compareTo = ByteBuff.compareTo(srcByteBuff, 100, 50, destMultiByteBuff, 100, 50);
524    assertTrue(compareTo == 0);
525
526    // Test src to dest first,second and third ByteBuffer
527    destMultiByteBuff.put(48, srcByteBuff, 32, 63);
528    compareTo = ByteBuff.compareTo(srcByteBuff, 32, 63, destMultiByteBuff, 48, 63);
529    assertTrue(compareTo == 0);
530
531    // Test src to dest first,second,third and fourth ByteBuffer
532    destMultiByteBuff.put(48, srcByteBuff, 32, 120);
533    compareTo = ByteBuff.compareTo(srcByteBuff, 32, 120, destMultiByteBuff, 48, 120);
534    assertTrue(compareTo == 0);
535
536    // Test src to dest first and second ByteBuffer
537    destMultiByteBuff.put(0, srcByteBuff, 132, 63);
538    compareTo = ByteBuff.compareTo(srcByteBuff, 132, 63, destMultiByteBuff, 0, 63);
539    assertTrue(compareTo == 0);
540
541    // Test src to dest second,third and fourth ByteBuffer
542    destMultiByteBuff.put(95, srcByteBuff, 132, 67);
543    compareTo = ByteBuff.compareTo(srcByteBuff, 132, 67, destMultiByteBuff, 95, 67);
544    assertTrue(compareTo == 0);
545
546    // Test src to dest fourth ByteBuffer
547    destMultiByteBuff.put(162, srcByteBuff, 132, 24);
548    compareTo = ByteBuff.compareTo(srcByteBuff, 132, 24, destMultiByteBuff, 162, 24);
549    assertTrue(compareTo == 0);
550
551    // Test src BufferUnderflowException
552    try {
553      destMultiByteBuff.put(0, srcByteBuff, 0, 300);
554      fail();
555    } catch (BufferUnderflowException e) {
556      assertTrue(e != null);
557    }
558
559    try {
560      destMultiByteBuff.put(95, srcByteBuff, 132, 89);
561      fail();
562    } catch (BufferUnderflowException e) {
563      assertTrue(e != null);
564    }
565
566    // Test dest BufferOverflowException
567    try {
568      destMultiByteBuff.put(100, srcByteBuff, 0, 101);
569      fail();
570    } catch (BufferOverflowException e) {
571      assertTrue(e != null);
572    }
573
574    try {
575      destMultiByteBuff.put(151, srcByteBuff, 132, 68);
576      fail();
577    } catch (BufferOverflowException e) {
578      assertTrue(e != null);
579    }
580
581    destMultiByteBuff = new MultiByteBuff(bb3, bb4);
582    try {
583      destMultiByteBuff.put(0, srcByteBuff, 0, 101);
584      fail();
585    } catch (BufferOverflowException e) {
586      assertTrue(e != null);
587    }
588  }
589
590  @Test
591  public void testPositionalPutByte() throws Exception {
592    ByteBuffer bb1 = ByteBuffer.allocate(50);
593    ByteBuffer bb2 = ByteBuffer.allocate(50);
594    ByteBuffer bb3 = ByteBuffer.allocate(50);
595    ByteBuffer bb4 = ByteBuffer.allocate(50);
596    MultiByteBuff srcMultiByteBuff = new MultiByteBuff(bb1, bb2, bb3, bb4);
597    for (int i = 1; i <= 200; i++) {
598      srcMultiByteBuff.put((byte) 0xff);
599    }
600
601    srcMultiByteBuff.put(20, (byte) 0);
602    byte val = srcMultiByteBuff.get(20);
603    assertTrue(val == 0);
604
605    srcMultiByteBuff.put(50, (byte) 0);
606    val = srcMultiByteBuff.get(50);
607    assertTrue(val == 0);
608
609    srcMultiByteBuff.put(80, (byte) 0);
610    val = srcMultiByteBuff.get(80);
611    assertTrue(val == 0);
612
613    srcMultiByteBuff.put(100, (byte) 0);
614    val = srcMultiByteBuff.get(100);
615    assertTrue(val == 0);
616
617    srcMultiByteBuff.put(121, (byte) 0);
618    val = srcMultiByteBuff.get(121);
619    assertTrue(val == 0);
620
621    srcMultiByteBuff.put(150, (byte) 0);
622    val = srcMultiByteBuff.get(150);
623    assertTrue(val == 0);
624
625    srcMultiByteBuff.put(180, (byte) 0);
626    val = srcMultiByteBuff.get(180);
627    assertTrue(val == 0);
628
629    try {
630      srcMultiByteBuff.put(200, (byte) 0);
631      fail();
632    } catch (IndexOutOfBoundsException e) {
633      assertTrue(e != null);
634    }
635
636    try {
637      srcMultiByteBuff.put(260, (byte) 0);
638      fail();
639    } catch (IndexOutOfBoundsException e) {
640      assertTrue(e != null);
641    }
642  }
643}