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