1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.core;
21  
22  import java.nio.BufferOverflowException;
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.ReadOnlyBufferException;
26  import java.nio.charset.CharacterCodingException;
27  import java.nio.charset.Charset;
28  import java.nio.charset.CharsetDecoder;
29  import java.nio.charset.CharsetEncoder;
30  import java.util.ArrayList;
31  import java.util.Date;
32  import java.util.EnumSet;
33  import java.util.List;
34  
35  import org.apache.mina.core.buffer.IoBuffer;
36  import org.apache.mina.util.Bar;
37  import org.junit.After;
38  import org.junit.Before;
39  import org.junit.Test;
40  
41  import static org.junit.Assert.assertFalse;
42  import static org.junit.Assert.assertTrue;
43  import static org.junit.Assert.assertEquals;
44  import static org.junit.Assert.assertSame;
45  import static org.junit.Assert.assertNotSame;
46  import static org.junit.Assert.fail;
47  
48  /**
49   * Tests {@link IoBuffer}.
50   *
51   * @author The Apache MINA Project (dev@mina.apache.org)
52   * @version $Rev: 706586 $, $Date: 2008-10-21 13:44:03 +0200 (Tue, 21 Oct 2008) $
53   */
54  public class IoBufferTest {
55  
56      /* public static void main(String[] args) {
57          junit.textui.TestRunner.run(IoBufferTest.class);
58      } */
59  
60      @Before
61      public void setUp() throws Exception {
62      }
63  
64      @After
65      public void tearDown() throws Exception {
66      }
67  
68      @Test
69      public void testAllocate() throws Exception {
70          for (int i = 10; i < 1048576 * 2; i = i * 11 / 10) // increase by 10%
71          {
72              IoBuffer buf = IoBuffer.allocate(i);
73              assertEquals(0, buf.position());
74              assertEquals(buf.capacity(), buf.remaining());
75              assertTrue(buf.capacity() >= i);
76              assertTrue(buf.capacity() < i * 2);
77          }
78      }
79  
80      @Test
81      public void testAutoExpand() throws Exception {
82          IoBuffer buf = IoBuffer.allocate(1);
83  
84          buf.put((byte) 0);
85          try {
86              buf.put((byte) 0);
87              fail();
88          } catch (BufferOverflowException e) {
89              // ignore
90          }
91  
92          buf.setAutoExpand(true);
93          buf.put((byte) 0);
94          assertEquals(2, buf.position());
95          assertEquals(2, buf.limit());
96          assertEquals(2, buf.capacity());
97  
98          buf.setAutoExpand(false);
99          try {
100             buf.put(3, (byte) 0);
101             fail();
102         } catch (IndexOutOfBoundsException e) {
103             // ignore
104         }
105 
106         buf.setAutoExpand(true);
107         buf.put(3, (byte) 0);
108         assertEquals(2, buf.position());
109         assertEquals(4, buf.limit());
110         assertEquals(4, buf.capacity());
111 
112         // Make sure the buffer is doubled up.
113         buf = IoBuffer.allocate(1).setAutoExpand(true);
114         int lastCapacity = buf.capacity();
115         for (int i = 0; i < 1048576; i ++) {
116             buf.put((byte) 0);
117             if (lastCapacity != buf.capacity()) {
118                 assertEquals(lastCapacity * 2, buf.capacity());
119                 lastCapacity = buf.capacity();
120             }
121         }
122     }
123 
124     @Test
125     public void testAutoExpandMark() throws Exception {
126         IoBuffer buf = IoBuffer.allocate(4).setAutoExpand(true);
127 
128         buf.put((byte) 0);
129         buf.put((byte) 0);
130         buf.put((byte) 0);
131 
132         // Position should be 3 when we reset this buffer.
133         buf.mark();
134 
135         // Overflow it
136         buf.put((byte) 0);
137         buf.put((byte) 0);
138 
139         assertEquals(5, buf.position());
140         buf.reset();
141         assertEquals(3, buf.position());
142     }
143 
144     @Test
145     public void testAutoShrink() throws Exception {
146         IoBuffer buf = IoBuffer.allocate(8).setAutoShrink(true);
147 
148         // Make sure the buffer doesn't shrink too much (less than the initial
149         // capacity.)
150         buf.sweep((byte) 1);
151         buf.fill(7);
152         buf.compact();
153         assertEquals(8, buf.capacity());
154         assertEquals(1, buf.position());
155         assertEquals(8, buf.limit());
156         buf.clear();
157         assertEquals(1, buf.get());
158 
159         // Expand the buffer.
160         buf.capacity(32).clear();
161         assertEquals(32, buf.capacity());
162 
163         // Make sure the buffer shrinks when only 1/4 is being used.
164         buf.sweep((byte) 1);
165         buf.fill(24);
166         buf.compact();
167         assertEquals(16, buf.capacity());
168         assertEquals(8, buf.position());
169         assertEquals(16, buf.limit());
170         buf.clear();
171         for (int i = 0; i < 8; i ++) {
172             assertEquals(1, buf.get());
173         }
174 
175         // Expand the buffer.
176         buf.capacity(32).clear();
177         assertEquals(32, buf.capacity());
178 
179         // Make sure the buffer shrinks when only 1/8 is being used.
180         buf.sweep((byte) 1);
181         buf.fill(28);
182         buf.compact();
183         assertEquals(8, buf.capacity());
184         assertEquals(4, buf.position());
185         assertEquals(8, buf.limit());
186         buf.clear();
187         for (int i = 0; i < 4; i ++) {
188             assertEquals(1, buf.get());
189         }
190 
191         // Expand the buffer.
192         buf.capacity(32).clear();
193         assertEquals(32, buf.capacity());
194 
195         // Make sure the buffer shrinks when 0 byte is being used.
196         buf.fill(32);
197         buf.compact();
198         assertEquals(8, buf.capacity());
199         assertEquals(0, buf.position());
200         assertEquals(8, buf.limit());
201 
202         // Expand the buffer.
203         buf.capacity(32).clear();
204         assertEquals(32, buf.capacity());
205 
206         // Make sure the buffer doesn't shrink when more than 1/4 is being used.
207         buf.sweep((byte) 1);
208         buf.fill(23);
209         buf.compact();
210         assertEquals(32, buf.capacity());
211         assertEquals(9, buf.position());
212         assertEquals(32, buf.limit());
213         buf.clear();
214         for (int i = 0; i < 9; i ++) {
215             assertEquals(1, buf.get());
216         }
217     }
218 
219     @Test
220     public void testGetString() throws Exception {
221         IoBuffer buf = IoBuffer.allocate(16);
222         CharsetDecoder decoder;
223 
224         Charset charset = Charset.forName("UTF-8");
225         buf.clear();
226         buf.putString("hello", charset.newEncoder());
227         buf.put((byte) 0);
228         buf.flip();
229         assertEquals("hello", buf.getString(charset.newDecoder()));
230 
231         buf.clear();
232         buf.putString("hello", charset.newEncoder());
233         buf.flip();
234         assertEquals("hello", buf.getString(charset.newDecoder()));
235 
236         decoder = Charset.forName("ISO-8859-1").newDecoder();
237         buf.clear();
238         buf.put((byte) 'A');
239         buf.put((byte) 'B');
240         buf.put((byte) 'C');
241         buf.put((byte) 0);
242 
243         buf.position(0);
244         assertEquals("ABC", buf.getString(decoder));
245         assertEquals(4, buf.position());
246 
247         buf.position(0);
248         buf.limit(1);
249         assertEquals("A", buf.getString(decoder));
250         assertEquals(1, buf.position());
251 
252         buf.clear();
253         assertEquals("ABC", buf.getString(10, decoder));
254         assertEquals(10, buf.position());
255 
256         buf.clear();
257         assertEquals("A", buf.getString(1, decoder));
258         assertEquals(1, buf.position());
259 
260         // Test a trailing garbage
261         buf.clear();
262         buf.put((byte) 'A');
263         buf.put((byte) 'B');
264         buf.put((byte) 0);
265         buf.put((byte) 'C');
266         buf.position(0);
267         assertEquals("AB", buf.getString(4, decoder));
268         assertEquals(4, buf.position());
269 
270         buf.clear();
271         buf.fillAndReset(buf.limit());
272         decoder = Charset.forName("UTF-16").newDecoder();
273         buf.put((byte) 0);
274         buf.put((byte) 'A');
275         buf.put((byte) 0);
276         buf.put((byte) 'B');
277         buf.put((byte) 0);
278         buf.put((byte) 'C');
279         buf.put((byte) 0);
280         buf.put((byte) 0);
281 
282         buf.position(0);
283         assertEquals("ABC", buf.getString(decoder));
284         assertEquals(8, buf.position());
285 
286         buf.position(0);
287         buf.limit(2);
288         assertEquals("A", buf.getString(decoder));
289         assertEquals(2, buf.position());
290 
291         buf.position(0);
292         buf.limit(3);
293         assertEquals("A", buf.getString(decoder));
294         assertEquals(2, buf.position());
295 
296         buf.clear();
297         assertEquals("ABC", buf.getString(10, decoder));
298         assertEquals(10, buf.position());
299 
300         buf.clear();
301         assertEquals("A", buf.getString(2, decoder));
302         assertEquals(2, buf.position());
303 
304         buf.clear();
305         try {
306             buf.getString(1, decoder);
307             fail();
308         } catch (IllegalArgumentException e) {
309             // ignore
310         }
311 
312         // Test getting strings from an empty buffer.
313         buf.clear();
314         buf.limit(0);
315         assertEquals("", buf.getString(decoder));
316         assertEquals("", buf.getString(2, decoder));
317 
318         // Test getting strings from non-empty buffer which is filled with 0x00
319         buf.clear();
320         buf.putInt(0);
321         buf.clear();
322         buf.limit(4);
323         assertEquals("", buf.getString(decoder));
324         assertEquals(2, buf.position());
325         assertEquals(4, buf.limit());
326 
327         buf.position(0);
328         assertEquals("", buf.getString(2, decoder));
329         assertEquals(2, buf.position());
330         assertEquals(4, buf.limit());
331     }
332 
333     @Test
334     public void testGetStringWithFailure() throws Exception {
335         String test = "\u30b3\u30e1\u30f3\u30c8\u7de8\u96c6";
336         IoBuffer buffer = IoBuffer.wrap(test.getBytes("Shift_JIS"));
337 
338         // Make sure the limit doesn't change when an exception arose.
339         int oldLimit = buffer.limit();
340         int oldPos = buffer.position();
341         try {
342             buffer.getString(3, Charset.forName("ASCII").newDecoder());
343             fail();
344         } catch (Exception e) {
345             assertEquals(oldLimit, buffer.limit());
346             assertEquals(oldPos, buffer.position());
347         }
348 
349         try {
350             buffer.getString(Charset.forName("ASCII").newDecoder());
351             fail();
352         } catch (Exception e) {
353             assertEquals(oldLimit, buffer.limit());
354             assertEquals(oldPos, buffer.position());
355         }
356     }
357 
358     @Test
359     public void testPutString() throws Exception {
360         CharsetEncoder encoder;
361         IoBuffer buf = IoBuffer.allocate(16);
362         encoder = Charset.forName("ISO-8859-1").newEncoder();
363 
364         buf.putString("ABC", encoder);
365         assertEquals(3, buf.position());
366         buf.clear();
367         assertEquals('A', buf.get(0));
368         assertEquals('B', buf.get(1));
369         assertEquals('C', buf.get(2));
370 
371         buf.putString("D", 5, encoder);
372         assertEquals(5, buf.position());
373         buf.clear();
374         assertEquals('D', buf.get(0));
375         assertEquals(0, buf.get(1));
376 
377         buf.putString("EFG", 2, encoder);
378         assertEquals(2, buf.position());
379         buf.clear();
380         assertEquals('E', buf.get(0));
381         assertEquals('F', buf.get(1));
382         assertEquals('C', buf.get(2)); // C may not be overwritten
383 
384         // UTF-16: We specify byte order to omit BOM.
385         encoder = Charset.forName("UTF-16BE").newEncoder();
386         buf.clear();
387 
388         buf.putString("ABC", encoder);
389         assertEquals(6, buf.position());
390         buf.clear();
391 
392         assertEquals(0, buf.get(0));
393         assertEquals('A', buf.get(1));
394         assertEquals(0, buf.get(2));
395         assertEquals('B', buf.get(3));
396         assertEquals(0, buf.get(4));
397         assertEquals('C', buf.get(5));
398 
399         buf.putString("D", 10, encoder);
400         assertEquals(10, buf.position());
401         buf.clear();
402         assertEquals(0, buf.get(0));
403         assertEquals('D', buf.get(1));
404         assertEquals(0, buf.get(2));
405         assertEquals(0, buf.get(3));
406 
407         buf.putString("EFG", 4, encoder);
408         assertEquals(4, buf.position());
409         buf.clear();
410         assertEquals(0, buf.get(0));
411         assertEquals('E', buf.get(1));
412         assertEquals(0, buf.get(2));
413         assertEquals('F', buf.get(3));
414         assertEquals(0, buf.get(4)); // C may not be overwritten
415         assertEquals('C', buf.get(5)); // C may not be overwritten
416 
417         // Test putting an emptry string
418         buf.putString("", encoder);
419         assertEquals(0, buf.position());
420         buf.putString("", 4, encoder);
421         assertEquals(4, buf.position());
422         assertEquals(0, buf.get(0));
423         assertEquals(0, buf.get(1));
424     }
425 
426     @Test
427     public void testGetPrefixedString() throws Exception {
428         IoBuffer buf = IoBuffer.allocate(16);
429         CharsetEncoder encoder;
430         CharsetDecoder decoder;
431         encoder = Charset.forName("ISO-8859-1").newEncoder();
432         decoder = Charset.forName("ISO-8859-1").newDecoder();
433 
434         buf.putShort((short) 3);
435         buf.putString("ABCD", encoder);
436         buf.clear();
437         assertEquals("ABC", buf.getPrefixedString(decoder));
438     }
439 
440     @Test
441     public void testPutPrefixedString() throws Exception {
442         CharsetEncoder encoder;
443         IoBuffer buf = IoBuffer.allocate(16);
444         buf.fillAndReset(buf.remaining());
445         encoder = Charset.forName("ISO-8859-1").newEncoder();
446 
447         // Without autoExpand
448         buf.putPrefixedString("ABC", encoder);
449         assertEquals(5, buf.position());
450         assertEquals(0, buf.get(0));
451         assertEquals(3, buf.get(1));
452         assertEquals('A', buf.get(2));
453         assertEquals('B', buf.get(3));
454         assertEquals('C', buf.get(4));
455 
456         buf.clear();
457         try {
458             buf.putPrefixedString("123456789012345", encoder);
459             fail();
460         } catch (BufferOverflowException e) {
461             // OK
462         }
463 
464         // With autoExpand
465         buf.clear();
466         buf.setAutoExpand(true);
467         buf.putPrefixedString("123456789012345", encoder);
468         assertEquals(17, buf.position());
469         assertEquals(0, buf.get(0));
470         assertEquals(15, buf.get(1));
471         assertEquals('1', buf.get(2));
472         assertEquals('2', buf.get(3));
473         assertEquals('3', buf.get(4));
474         assertEquals('4', buf.get(5));
475         assertEquals('5', buf.get(6));
476         assertEquals('6', buf.get(7));
477         assertEquals('7', buf.get(8));
478         assertEquals('8', buf.get(9));
479         assertEquals('9', buf.get(10));
480         assertEquals('0', buf.get(11));
481         assertEquals('1', buf.get(12));
482         assertEquals('2', buf.get(13));
483         assertEquals('3', buf.get(14));
484         assertEquals('4', buf.get(15));
485         assertEquals('5', buf.get(16));
486     }
487 
488     @Test
489     public void testPutPrefixedStringWithPrefixLength() throws Exception {
490         CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder();
491         IoBuffer buf = IoBuffer.allocate(16).sweep().setAutoExpand(true);
492 
493         buf.putPrefixedString("A", 1, encoder);
494         assertEquals(2, buf.position());
495         assertEquals(1, buf.get(0));
496         assertEquals('A', buf.get(1));
497 
498         buf.sweep();
499         buf.putPrefixedString("A", 2, encoder);
500         assertEquals(3, buf.position());
501         assertEquals(0, buf.get(0));
502         assertEquals(1, buf.get(1));
503         assertEquals('A', buf.get(2));
504 
505         buf.sweep();
506         buf.putPrefixedString("A", 4, encoder);
507         assertEquals(5, buf.position());
508         assertEquals(0, buf.get(0));
509         assertEquals(0, buf.get(1));
510         assertEquals(0, buf.get(2));
511         assertEquals(1, buf.get(3));
512         assertEquals('A', buf.get(4));
513     }
514 
515     @Test
516     public void testPutPrefixedStringWithPadding() throws Exception {
517         CharsetEncoder encoder = Charset.forName("ISO-8859-1").newEncoder();
518         IoBuffer buf = IoBuffer.allocate(16).sweep().setAutoExpand(true);
519 
520         buf.putPrefixedString("A", 1, 2, (byte) 32, encoder);
521         assertEquals(3, buf.position());
522         assertEquals(2, buf.get(0));
523         assertEquals('A', buf.get(1));
524         assertEquals(' ', buf.get(2));
525 
526         buf.sweep();
527         buf.putPrefixedString("A", 1, 4, (byte) 32, encoder);
528         assertEquals(5, buf.position());
529         assertEquals(4, buf.get(0));
530         assertEquals('A', buf.get(1));
531         assertEquals(' ', buf.get(2));
532         assertEquals(' ', buf.get(3));
533         assertEquals(' ', buf.get(4));
534     }
535 
536     @Test
537     public void testWideUtf8Characters() throws Exception {
538         Runnable r = new Runnable() {
539             public void run() {
540                 IoBuffer buffer = IoBuffer.allocate(1);
541                 buffer.setAutoExpand(true);
542 
543                 Charset charset = Charset.forName("UTF-8");
544 
545                 CharsetEncoder encoder = charset.newEncoder();
546 
547                 for (int i = 0; i < 5; i++) {
548                     try {
549                         buffer.putString("\u89d2", encoder);
550                         buffer.putPrefixedString("\u89d2", encoder);
551                     } catch (CharacterCodingException e) {
552                         fail(e.getMessage());
553                     }
554                 }
555             }
556         };
557 
558         Thread t = new Thread(r);
559         t.setDaemon(true);
560         t.start();
561 
562         for (int i = 0; i < 50; i++) {
563             Thread.sleep(100);
564             if (!t.isAlive()) {
565                 break;
566             }
567         }
568 
569         if (t.isAlive()) {
570             t.interrupt();
571 
572             fail("Went into endless loop trying to encode character");
573         }
574     }
575 
576     @Test
577     public void testObjectSerialization() throws Exception {
578         IoBuffer buf = IoBuffer.allocate(16);
579         buf.setAutoExpand(true);
580         List<Object> o = new ArrayList<Object>();
581         o.add(new Date());
582         o.add(long.class);
583 
584         // Test writing an object.
585         buf.putObject(o);
586 
587         // Test reading an object.
588         buf.clear();
589         Object o2 = buf.getObject();
590         assertEquals(o, o2);
591 
592         // This assertion is just to make sure that deserialization occurred.
593         assertNotSame(o, o2);
594     }
595 
596     @Test
597     public void testInheritedObjectSerialization() throws Exception {
598         IoBuffer buf = IoBuffer.allocate(16);
599         buf.setAutoExpand(true);
600 
601         Bar expected = new Bar();
602         expected.setFooValue(0x12345678);
603         expected.setBarValue(0x90ABCDEF);
604 
605         // Test writing an object.
606         buf.putObject(expected);
607 
608         // Test reading an object.
609         buf.clear();
610         Bar actual = (Bar) buf.getObject();
611         assertSame(Bar.class, actual.getClass());
612         assertEquals(expected.getFooValue(), actual.getFooValue());
613         assertEquals(expected.getBarValue(), actual.getBarValue());
614 
615         // This assertion is just to make sure that deserialization occurred.
616         assertNotSame(expected, actual);
617     }
618 
619     @Test
620     public void testSweepWithZeros() throws Exception {
621         IoBuffer buf = IoBuffer.allocate(4);
622         buf.putInt(0xdeadbeef);
623         buf.clear();
624         assertEquals(0xdeadbeef, buf.getInt());
625         assertEquals(4, buf.position());
626         assertEquals(4, buf.limit());
627 
628         buf.sweep();
629         assertEquals(0, buf.position());
630         assertEquals(4, buf.limit());
631         assertEquals(0x0, buf.getInt());
632     }
633 
634     @Test
635     public void testSweepNonZeros() throws Exception {
636         IoBuffer buf = IoBuffer.allocate(4);
637         buf.putInt(0xdeadbeef);
638         buf.clear();
639         assertEquals(0xdeadbeef, buf.getInt());
640         assertEquals(4, buf.position());
641         assertEquals(4, buf.limit());
642 
643         buf.sweep((byte) 0x45);
644         assertEquals(0, buf.position());
645         assertEquals(4, buf.limit());
646         assertEquals(0x45454545, buf.getInt());
647     }
648 
649     @Test
650     public void testWrapNioBuffer() throws Exception {
651         ByteBuffer nioBuf = ByteBuffer.allocate(10);
652         nioBuf.position(3);
653         nioBuf.limit(7);
654 
655         IoBuffer buf = IoBuffer.wrap(nioBuf);
656         assertEquals(3, buf.position());
657         assertEquals(7, buf.limit());
658         assertEquals(10, buf.capacity());
659     }
660 
661     @Test
662     public void testWrapSubArray() throws Exception {
663         byte[] array = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
664 
665         IoBuffer buf = IoBuffer.wrap(array, 3, 4);
666         assertEquals(3, buf.position());
667         assertEquals(7, buf.limit());
668         assertEquals(10, buf.capacity());
669 
670         buf.clear();
671         assertEquals(0, buf.position());
672         assertEquals(10, buf.limit());
673         assertEquals(10, buf.capacity());
674     }
675 
676     @Test
677     public void testDuplicate() throws Exception {
678         IoBuffer original;
679         IoBuffer duplicate;
680 
681         // Test if the buffer is duplicated correctly.
682         original = IoBuffer.allocate(16).sweep();
683         original.position(4);
684         original.limit(10);
685         duplicate = original.duplicate();
686         original.put(4, (byte) 127);
687         assertEquals(4, duplicate.position());
688         assertEquals(10, duplicate.limit());
689         assertEquals(16, duplicate.capacity());
690         assertNotSame(original.buf(), duplicate.buf());
691         assertSame(original.buf().array(), duplicate.buf().array());
692         assertEquals(127, duplicate.get(4));
693 
694         // Test a duplicate of a duplicate.
695         original = IoBuffer.allocate(16);
696         duplicate = original.duplicate().duplicate();
697         assertNotSame(original.buf(), duplicate.buf());
698         assertSame(original.buf().array(), duplicate.buf().array());
699 
700         // Try to expand.
701         original = IoBuffer.allocate(16);
702         original.setAutoExpand(true);
703         duplicate = original.duplicate();
704         assertFalse(original.isAutoExpand());
705 
706         try {
707             original.setAutoExpand(true);
708             fail();
709         } catch (IllegalStateException e) {
710             // OK
711         }
712 
713         try {
714             duplicate.setAutoExpand(true);
715             fail();
716         } catch (IllegalStateException e) {
717             // OK
718         }
719     }
720 
721     @Test
722     public void testSlice() throws Exception {
723         IoBuffer original;
724         IoBuffer slice;
725 
726         // Test if the buffer is sliced correctly.
727         original = IoBuffer.allocate(16).sweep();
728         original.position(4);
729         original.limit(10);
730         slice = original.slice();
731         original.put(4, (byte) 127);
732         assertEquals(0, slice.position());
733         assertEquals(6, slice.limit());
734         assertEquals(6, slice.capacity());
735         assertNotSame(original.buf(), slice.buf());
736         assertEquals(127, slice.get(0));
737     }
738 
739     @Test
740     public void testReadOnlyBuffer() throws Exception {
741         IoBuffer original;
742         IoBuffer duplicate;
743 
744         // Test if the buffer is duplicated correctly.
745         original = IoBuffer.allocate(16).sweep();
746         original.position(4);
747         original.limit(10);
748         duplicate = original.asReadOnlyBuffer();
749         original.put(4, (byte) 127);
750         assertEquals(4, duplicate.position());
751         assertEquals(10, duplicate.limit());
752         assertEquals(16, duplicate.capacity());
753         assertNotSame(original.buf(), duplicate.buf());
754         assertEquals(127, duplicate.get(4));
755 
756         // Try to expand.
757         try {
758             original = IoBuffer.allocate(16);
759             duplicate = original.asReadOnlyBuffer();
760             duplicate.putString("A very very very very looooooong string",
761                     Charset.forName("ISO-8859-1").newEncoder());
762             fail();
763         } catch (ReadOnlyBufferException e) {
764             // OK
765         }
766     }
767 
768     @Test
769     public void testGetUnsigned() throws Exception {
770         IoBuffer buf = IoBuffer.allocate(16);
771         buf.put((byte) 0xA4);
772         buf.put((byte) 0xD0);
773         buf.put((byte) 0xB3);
774         buf.put((byte) 0xCD);
775         buf.flip();
776 
777         buf.order(ByteOrder.LITTLE_ENDIAN);
778 
779         buf.mark();
780         assertEquals(0xA4, buf.getUnsigned());
781         buf.reset();
782         assertEquals(0xD0A4, buf.getUnsignedShort());
783         buf.reset();
784         assertEquals(0xCDB3D0A4L, buf.getUnsignedInt());
785     }
786 
787     @Test
788     public void testIndexOf() throws Exception {
789         boolean direct = false;
790         for (int i = 0; i < 2; i++, direct = !direct) {
791             IoBuffer buf = IoBuffer.allocate(16, direct);
792             buf.put((byte) 0x1);
793             buf.put((byte) 0x2);
794             buf.put((byte) 0x3);
795             buf.put((byte) 0x4);
796             buf.put((byte) 0x1);
797             buf.put((byte) 0x2);
798             buf.put((byte) 0x3);
799             buf.put((byte) 0x4);
800             buf.position(2);
801             buf.limit(5);
802 
803             assertEquals(4, buf.indexOf((byte) 0x1));
804             assertEquals(-1, buf.indexOf((byte) 0x2));
805             assertEquals(2, buf.indexOf((byte) 0x3));
806             assertEquals(3, buf.indexOf((byte) 0x4));
807         }
808     }
809 
810     // We need an enum with 64 values
811     private static enum TestEnum {
812         E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E77, E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64
813     }
814 
815     private static enum TooBigEnum {
816         E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E77, E48, E49, E50, E51, E52, E53, E54, E55, E56, E57, E58, E59, E60, E61, E62, E63, E64, E65
817     }
818 
819     @Test
820     public void testPutEnumSet() {
821         IoBuffer buf = IoBuffer.allocate(8);
822 
823         // Test empty set
824         buf.putEnumSet(EnumSet.noneOf(TestEnum.class));
825         buf.flip();
826         assertEquals(0, buf.get());
827 
828         buf.clear();
829         buf.putEnumSetShort(EnumSet.noneOf(TestEnum.class));
830         buf.flip();
831         assertEquals(0, buf.getShort());
832 
833         buf.clear();
834         buf.putEnumSetInt(EnumSet.noneOf(TestEnum.class));
835         buf.flip();
836         assertEquals(0, buf.getInt());
837 
838         buf.clear();
839         buf.putEnumSetLong(EnumSet.noneOf(TestEnum.class));
840         buf.flip();
841         assertEquals(0, buf.getLong());
842 
843         // Test complete set
844         buf.clear();
845         buf.putEnumSet(EnumSet.range(TestEnum.E1, TestEnum.E8));
846         buf.flip();
847         assertEquals((byte) -1, buf.get());
848 
849         buf.clear();
850         buf.putEnumSetShort(EnumSet.range(TestEnum.E1, TestEnum.E16));
851         buf.flip();
852         assertEquals((short) -1, buf.getShort());
853 
854         buf.clear();
855         buf.putEnumSetInt(EnumSet.range(TestEnum.E1, TestEnum.E32));
856         buf.flip();
857         assertEquals(-1, buf.getInt());
858 
859         buf.clear();
860         buf.putEnumSetLong(EnumSet.allOf(TestEnum.class));
861         buf.flip();
862         assertEquals(-1L, buf.getLong());
863 
864         // Test high bit set
865         buf.clear();
866         buf.putEnumSet(EnumSet.of(TestEnum.E8));
867         buf.flip();
868         assertEquals(Byte.MIN_VALUE, buf.get());
869 
870         buf.clear();
871         buf.putEnumSetShort(EnumSet.of(TestEnum.E16));
872         buf.flip();
873         assertEquals(Short.MIN_VALUE, buf.getShort());
874 
875         buf.clear();
876         buf.putEnumSetInt(EnumSet.of(TestEnum.E32));
877         buf.flip();
878         assertEquals(Integer.MIN_VALUE, buf.getInt());
879 
880         buf.clear();
881         buf.putEnumSetLong(EnumSet.of(TestEnum.E64));
882         buf.flip();
883         assertEquals(Long.MIN_VALUE, buf.getLong());
884 
885         // Test high low bits set
886         buf.clear();
887         buf.putEnumSet(EnumSet.of(TestEnum.E1, TestEnum.E8));
888         buf.flip();
889         assertEquals(Byte.MIN_VALUE + 1, buf.get());
890 
891         buf.clear();
892         buf.putEnumSetShort(EnumSet.of(TestEnum.E1, TestEnum.E16));
893         buf.flip();
894         assertEquals(Short.MIN_VALUE + 1, buf.getShort());
895 
896         buf.clear();
897         buf.putEnumSetInt(EnumSet.of(TestEnum.E1, TestEnum.E32));
898         buf.flip();
899         assertEquals(Integer.MIN_VALUE + 1, buf.getInt());
900 
901         buf.clear();
902         buf.putEnumSetLong(EnumSet.of(TestEnum.E1, TestEnum.E64));
903         buf.flip();
904         assertEquals(Long.MIN_VALUE + 1, buf.getLong());
905     }
906 
907     @Test
908     public void testGetEnumSet() {
909         IoBuffer buf = IoBuffer.allocate(8);
910 
911         // Test empty set
912         buf.put((byte) 0);
913         buf.flip();
914         assertEquals(EnumSet.noneOf(TestEnum.class), buf
915                 .getEnumSet(TestEnum.class));
916 
917         buf.clear();
918         buf.putShort((short) 0);
919         buf.flip();
920         assertEquals(EnumSet.noneOf(TestEnum.class), buf
921                 .getEnumSet(TestEnum.class));
922 
923         buf.clear();
924         buf.putInt(0);
925         buf.flip();
926         assertEquals(EnumSet.noneOf(TestEnum.class), buf
927                 .getEnumSet(TestEnum.class));
928 
929         buf.clear();
930         buf.putLong(0L);
931         buf.flip();
932         assertEquals(EnumSet.noneOf(TestEnum.class), buf
933                 .getEnumSet(TestEnum.class));
934 
935         // Test complete set
936         buf.clear();
937         buf.put((byte) -1);
938         buf.flip();
939         assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E8), buf
940                 .getEnumSet(TestEnum.class));
941 
942         buf.clear();
943         buf.putShort((short) -1);
944         buf.flip();
945         assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E16), buf
946                 .getEnumSetShort(TestEnum.class));
947 
948         buf.clear();
949         buf.putInt(-1);
950         buf.flip();
951         assertEquals(EnumSet.range(TestEnum.E1, TestEnum.E32), buf
952                 .getEnumSetInt(TestEnum.class));
953 
954         buf.clear();
955         buf.putLong(-1L);
956         buf.flip();
957         assertEquals(EnumSet.allOf(TestEnum.class), buf
958                 .getEnumSetLong(TestEnum.class));
959 
960         // Test high bit set
961         buf.clear();
962         buf.put(Byte.MIN_VALUE);
963         buf.flip();
964         assertEquals(EnumSet.of(TestEnum.E8), buf.getEnumSet(TestEnum.class));
965 
966         buf.clear();
967         buf.putShort(Short.MIN_VALUE);
968         buf.flip();
969         assertEquals(EnumSet.of(TestEnum.E16), buf
970                 .getEnumSetShort(TestEnum.class));
971 
972         buf.clear();
973         buf.putInt(Integer.MIN_VALUE);
974         buf.flip();
975         assertEquals(EnumSet.of(TestEnum.E32), buf
976                 .getEnumSetInt(TestEnum.class));
977 
978         buf.clear();
979         buf.putLong(Long.MIN_VALUE);
980         buf.flip();
981         assertEquals(EnumSet.of(TestEnum.E64), buf
982                 .getEnumSetLong(TestEnum.class));
983 
984         // Test high low bits set
985         buf.clear();
986         byte b = Byte.MIN_VALUE + 1;
987         buf.put(b);
988         buf.flip();
989         assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E8), buf
990                 .getEnumSet(TestEnum.class));
991 
992         buf.clear();
993         short s = Short.MIN_VALUE + 1;
994         buf.putShort(s);
995         buf.flip();
996         assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E16), buf
997                 .getEnumSetShort(TestEnum.class));
998 
999         buf.clear();
1000         buf.putInt(Integer.MIN_VALUE + 1);
1001         buf.flip();
1002         assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E32), buf
1003                 .getEnumSetInt(TestEnum.class));
1004 
1005         buf.clear();
1006         buf.putLong(Long.MIN_VALUE + 1);
1007         buf.flip();
1008         assertEquals(EnumSet.of(TestEnum.E1, TestEnum.E64), buf
1009                 .getEnumSetLong(TestEnum.class));
1010     }
1011 
1012     @Test
1013     public void testBitVectorOverFlow() {
1014         IoBuffer buf = IoBuffer.allocate(8);
1015         try {
1016             buf.putEnumSet(EnumSet.of(TestEnum.E9));
1017             fail("Should have thrown IllegalArgumentException");
1018         } catch (IllegalArgumentException e) {
1019             // pass
1020         }
1021 
1022         try {
1023             buf.putEnumSetShort(EnumSet.of(TestEnum.E17));
1024             fail("Should have thrown IllegalArgumentException");
1025         } catch (IllegalArgumentException e) {
1026             // pass
1027         }
1028 
1029         try {
1030             buf.putEnumSetInt(EnumSet.of(TestEnum.E33));
1031             fail("Should have thrown IllegalArgumentException");
1032         } catch (IllegalArgumentException e) {
1033             // pass
1034         }
1035 
1036         try {
1037             buf.putEnumSetLong(EnumSet.of(TooBigEnum.E65));
1038             fail("Should have thrown IllegalArgumentException");
1039         } catch (IllegalArgumentException e) {
1040             // pass
1041         }
1042     }
1043 
1044     @Test
1045     public void testGetPutEnum() {
1046         IoBuffer buf = IoBuffer.allocate(4);
1047 
1048         buf.putEnum(TestEnum.E64);
1049         buf.flip();
1050         assertEquals(TestEnum.E64, buf.getEnum(TestEnum.class));
1051 
1052         buf.clear();
1053         buf.putEnumShort(TestEnum.E64);
1054         buf.flip();
1055         assertEquals(TestEnum.E64, buf.getEnumShort(TestEnum.class));
1056 
1057         buf.clear();
1058         buf.putEnumInt(TestEnum.E64);
1059         buf.flip();
1060         assertEquals(TestEnum.E64, buf.getEnumInt(TestEnum.class));
1061     }
1062 
1063     @Test
1064     public void testGetMediumInt() {
1065         IoBuffer buf = IoBuffer.allocate(3);
1066 
1067         buf.put((byte) 0x01);
1068         buf.put((byte) 0x02);
1069         buf.put((byte) 0x03);
1070         assertEquals(3, buf.position());
1071 
1072         buf.flip();
1073         assertEquals(0x010203, buf.getMediumInt());
1074         assertEquals(0x010203, buf.getMediumInt(0));
1075         buf.flip();
1076         assertEquals(0x010203, buf.getUnsignedMediumInt());
1077         assertEquals(0x010203, buf.getUnsignedMediumInt(0));
1078         buf.flip();
1079         assertEquals(0x010203, buf.getUnsignedMediumInt());
1080         buf.flip().order(ByteOrder.LITTLE_ENDIAN);
1081         assertEquals(0x030201, buf.getMediumInt());
1082         assertEquals(0x030201, buf.getMediumInt(0));
1083 
1084         // Test max medium int
1085         buf.flip().order(ByteOrder.BIG_ENDIAN);
1086         buf.put((byte) 0x7f);
1087         buf.put((byte) 0xff);
1088         buf.put((byte) 0xff);
1089         buf.flip();
1090         assertEquals(0x7fffff, buf.getMediumInt());
1091         assertEquals(0x7fffff, buf.getMediumInt(0));
1092 
1093         // Test negative number
1094         buf.flip().order(ByteOrder.BIG_ENDIAN);
1095         buf.put((byte) 0xff);
1096         buf.put((byte) 0x02);
1097         buf.put((byte) 0x03);
1098         buf.flip();
1099 
1100         assertEquals(0xffff0203, buf.getMediumInt());
1101         assertEquals(0xffff0203, buf.getMediumInt(0));
1102         buf.flip();
1103 
1104         assertEquals(0x00ff0203, buf.getUnsignedMediumInt());
1105         assertEquals(0x00ff0203, buf.getUnsignedMediumInt(0));
1106     }
1107 
1108     @Test
1109     public void testPutMediumInt() {
1110         IoBuffer buf = IoBuffer.allocate(3);
1111 
1112         checkMediumInt(buf, 0);
1113         checkMediumInt(buf, 1);
1114         checkMediumInt(buf, -1);
1115         checkMediumInt(buf, 0x7fffff);
1116     }
1117 
1118     private void checkMediumInt(IoBuffer buf, int x) {
1119         buf.putMediumInt(x);
1120         assertEquals(3, buf.position());
1121         buf.flip();
1122         assertEquals(x, buf.getMediumInt());
1123         assertEquals(3, buf.position());
1124 
1125         buf.putMediumInt(0, x);
1126         assertEquals(3, buf.position());
1127         assertEquals(x, buf.getMediumInt(0));
1128 
1129         buf.flip();
1130     }
1131 }