1/*
2 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* Type-specific source code for unit test
25 *
26 * Regenerate the BasicX classes via genBasic.sh whenever this file changes.
27 * We check in the generated source files so that the test tree can be used
28 * independently of the rest of the source tree.
29 */
30package test.java.nio.Buffer;
31
32#warn This file is preprocessed before being compiled
33
34#if[byte]
35import java.io.IOException;
36import java.io.UncheckedIOException;
37#end[byte]
38import java.nio.*;
39import java.util.function.Supplier;
40#if[byte]
41import java.nio.channels.FileChannel;
42import java.nio.file.Files;
43import java.nio.file.Path;
44import java.util.Random;
45#end[byte]
46
47
48import static org.testng.Assert.assertEquals;
49
50
51public class Basic$Type$
52    extends Basic
53{
54
55    private static final $type$[] VALUES = {
56        $Fulltype$.MIN_VALUE,
57        ($type$) -1,
58        ($type$) 0,
59        ($type$) 1,
60        $Fulltype$.MAX_VALUE,
61#if[float]
62        $Fulltype$.NEGATIVE_INFINITY,
63        $Fulltype$.POSITIVE_INFINITY,
64        $Fulltype$.NaN,
65        ($type$) -0.0,
66#end[float]
67#if[double]
68        $Fulltype$.NEGATIVE_INFINITY,
69        $Fulltype$.POSITIVE_INFINITY,
70        $Fulltype$.NaN,
71        ($type$) -0.0,
72#end[double]
73    };
74
75    private static void relGet($Type$Buffer b) {
76        int n = b.capacity();
77        for (int i = 0; i < n; i++)
78            ck(b, (long)b.get(), (long)(($type$)ic(i)));
79        b.rewind();
80    }
81
82    private static void relGet($Type$Buffer b, int start) {
83        int n = b.remaining();
84        for (int i = start; i < n; i++)
85            ck(b, (long)b.get(), (long)(($type$)ic(i)));
86        b.rewind();
87    }
88
89    private static void absGet($Type$Buffer b) {
90        int n = b.capacity();
91        for (int i = 0; i < n; i++)
92            ck(b, (long)b.get(), (long)(($type$)ic(i)));
93        b.rewind();
94    }
95
96    private static void bulkGet($Type$Buffer b) {
97        int n = b.capacity();
98        $type$[] a = new $type$[n + 7];
99        b.get(a, 7, n);
100        for (int i = 0; i < n; i++) {
101            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
102        }
103    }
104
105    private static void absBulkGet($Type$Buffer b) {
106        int n = b.capacity();
107        int len = n - 7*2;
108        $type$[] a = new $type$[n + 7];
109        b.position(42);
110        b.get(7, a, 7, len);
111        ck(b, b.position() == 42);
112        for (int i = 0; i < len; i++) {
113            ck(b, (long)a[i + 7], (long)(($type$)ic(i)));
114        }
115    }
116
117    private static void relPut($Type$Buffer b) {
118        int n = b.capacity();
119        b.clear();
120        for (int i = 0; i < n; i++)
121            b.put(($type$)ic(i));
122        b.flip();
123    }
124
125    private static void absPut($Type$Buffer b) {
126        int n = b.capacity();
127        b.clear();
128        for (int i = 0; i < n; i++)
129            b.put(i, ($type$)ic(i));
130        b.limit(n);
131        b.position(0);
132    }
133
134    private static void bulkPutArray($Type$Buffer b) {
135        int n = b.capacity();
136        b.clear();
137        $type$[] a = new $type$[n + 7];
138        for (int i = 0; i < n; i++)
139            a[i + 7] = ($type$)ic(i);
140        b.put(a, 7, n);
141        b.flip();
142    }
143
144    private static void bulkPutBuffer($Type$Buffer b) {
145        int n = b.capacity();
146        b.clear();
147        $Type$Buffer c = $Type$Buffer.allocate(n + 7);
148        c.position(7);
149        for (int i = 0; i < n; i++)
150            c.put(($type$)ic(i));
151        c.flip();
152        c.position(7);
153        b.put(c);
154        b.flip();
155        try {
156            b.put(b);
157            fail("IllegalArgumentException expected for put into same buffer");
158        } catch (IllegalArgumentException e) {
159            if (e.getMessage() == null) {
160                fail("Non-null IllegalArgumentException message expected from"
161                     + " put into same buffer");
162            }
163        }
164    }
165
166    private static void absBulkPutArray($Type$Buffer b) {
167        int n = b.capacity();
168        b.clear();
169        int lim = n - 7;
170        int len = lim - 7;
171        b.limit(lim);
172        $type$[] a = new $type$[len + 7];
173        for (int i = 0; i < len; i++)
174            a[i + 7] = ($type$)ic(i);
175        b.position(42);
176        b.put(7, a, 7, len);
177        ck(b, b.position() == 42);
178    }
179
180    //6231529
181    private static void callReset($Type$Buffer b) {
182        b.position(0);
183        b.mark();
184
185        b.duplicate().reset();
186        b.asReadOnlyBuffer().reset();
187    }
188
189#if[byte]
190#else[byte]
191    // 6221101-6234263
192
193    private static void putBuffer() {
194        final int cap = 10;
195
196        $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
197        $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer();
198        direct1.put(nondirect1);
199
200        $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
201        $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer();
202        nondirect2.put(direct2);
203
204        $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
205        $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer();
206        direct3.put(direct4);
207
208        $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer();
209        $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer();
210        nondirect3.put(nondirect4);
211    }
212#end[byte]
213
214#if[char]
215
216    private static void bulkPutString($Type$Buffer b) {
217        int n = b.capacity();
218        b.clear();
219        StringBuilder sb = new StringBuilder(n + 7);
220        sb.append("1234567");
221        for (int i = 0; i < n; i++)
222            sb.append((char)ic(i));
223        b.put(sb.toString(), 7, 7 + n);
224        b.flip();
225    }
226
227#end[char]
228
229    private static void checkSlice($Type$Buffer b, $Type$Buffer slice) {
230        ck(slice, 0, slice.position());
231        ck(slice, b.remaining(), slice.limit());
232        ck(slice, b.remaining(), slice.capacity());
233        if (b.isDirect() != slice.isDirect())
234            fail("Lost direction", slice);
235        if (b.isReadOnly() != slice.isReadOnly())
236            fail("Lost read-only", slice);
237    }
238
239#if[byte]
240
241    private static void checkBytes(ByteBuffer b, byte[] bs) {
242        int n = bs.length;
243        int p = b.position();
244        if (b.order() == ByteOrder.BIG_ENDIAN) {
245            for (int i = 0; i < n; i++) {
246                ck(b, b.get(), bs[i]);
247            }
248        } else {
249            for (int i = n - 1; i >= 0; i--) {
250                ck(b, b.get(), bs[i]);
251            }
252        }
253        b.position(p);
254    }
255
256    private static void compact(Buffer b) {
257        try {
258            Class<?> cl = b.getClass();
259            java.lang.reflect.Method m = cl.getDeclaredMethod("compact");
260            m.setAccessible(true);
261            m.invoke(b);
262        } catch (Exception e) {
263            fail(e.getMessage(), b);
264        }
265    }
266
267    private static void checkInvalidMarkException(final Buffer b) {
268        tryCatch(b, InvalidMarkException.class, () -> {
269                b.mark();
270                compact(b);
271                b.reset();
272            });
273    }
274
275    private static void testViews(int level, ByteBuffer b, boolean direct) {
276
277        ShortBuffer sb = b.asShortBuffer();
278        BasicShort.test(level, sb, direct);
279        checkBytes(b, new byte[] { 0, (byte)ic(0) });
280        checkInvalidMarkException(sb);
281
282        CharBuffer cb = b.asCharBuffer();
283        BasicChar.test(level, cb, direct);
284        checkBytes(b, new byte[] { 0, (byte)ic(0) });
285        checkInvalidMarkException(cb);
286
287        IntBuffer ib = b.asIntBuffer();
288        BasicInt.test(level, ib, direct);
289        checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
290        checkInvalidMarkException(ib);
291
292        LongBuffer lb = b.asLongBuffer();
293        BasicLong.test(level, lb, direct);
294        checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
295        checkInvalidMarkException(lb);
296
297        FloatBuffer fb = b.asFloatBuffer();
298        BasicFloat.test(level, fb, direct);
299        checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
300        checkInvalidMarkException(fb);
301
302        DoubleBuffer db = b.asDoubleBuffer();
303        BasicDouble.test(level, db, direct);
304        checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
305        checkInvalidMarkException(db);
306    }
307
308    private static void testHet(int level, ByteBuffer b) {
309
310        int p = b.position();
311        b.limit(b.capacity());
312        show(level, b);
313        out.print("    put:");
314
315        b.putChar((char)1);
316        b.putChar((char)Character.MAX_VALUE);
317        out.print(" char");
318
319        b.putShort((short)1);
320        b.putShort((short)Short.MAX_VALUE);
321        out.print(" short");
322
323        b.putInt(1);
324        b.putInt(Integer.MAX_VALUE);
325        out.print(" int");
326
327        b.putLong((long)1);
328        b.putLong((long)Long.MAX_VALUE);
329        out.print(" long");
330
331        b.putFloat((float)1);
332        b.putFloat((float)Float.MIN_VALUE);
333        b.putFloat((float)Float.MAX_VALUE);
334        out.print(" float");
335
336        b.putDouble((double)1);
337        b.putDouble((double)Double.MIN_VALUE);
338        b.putDouble((double)Double.MAX_VALUE);
339        out.print(" double");
340
341        out.println();
342        b.limit(b.position());
343        b.position(p);
344        show(level, b);
345        out.print("    get:");
346
347        ck(b, b.getChar(), 1);
348        ck(b, b.getChar(), Character.MAX_VALUE);
349        out.print(" char");
350
351        ck(b, b.getShort(), 1);
352        ck(b, b.getShort(), Short.MAX_VALUE);
353        out.print(" short");
354
355        ck(b, b.getInt(), 1);
356        ck(b, b.getInt(), Integer.MAX_VALUE);
357        out.print(" int");
358
359        ck(b, b.getLong(), 1);
360        ck(b, b.getLong(), Long.MAX_VALUE);
361        out.print(" long");
362
363        ck(b, (long)b.getFloat(), 1);
364        ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE);
365        ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE);
366        out.print(" float");
367
368        ck(b, (long)b.getDouble(), 1);
369        ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE);
370        ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE);
371        out.print(" double");
372
373        out.println();
374
375    }
376
377    private static void testAlign(final ByteBuffer b, boolean direct) {
378        // index out-of bounds
379        catchIllegalArgument(b, () -> b.alignmentOffset(-1, (short) 1));
380
381        // unit size values
382        catchIllegalArgument(b, () -> b.alignmentOffset(0, (short) 0));
383        for (int us = 1; us < 65; us++) {
384            int _us = us;
385            if ((us & (us - 1)) != 0) {
386                // unit size not a power of two
387                catchIllegalArgument(b, () -> b.alignmentOffset(0, _us));
388            } else {
389                if (direct || us <= 8) {
390                    b.alignmentOffset(0, us);
391                } else {
392                    // unit size > 8 with non-direct buffer
393                    tryCatch(b, UnsupportedOperationException.class,
394                            () -> b.alignmentOffset(0, _us));
395                }
396            }
397        }
398
399        // Probe for long misalignment at index zero for a newly created buffer
400        ByteBuffer empty =
401                direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
402        int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
403
404        if (direct) {
405            // Freshly created direct byte buffers should be aligned at index 0
406            // for ref and primitive values (see Unsafe.allocateMemory)
407            if (longMisalignmentAtZero != 0) {
408                fail("Direct byte buffer misaligned at index 0"
409                        + " for ref and primitive values "
410                        + longMisalignmentAtZero);
411            }
412        } else {
413            // For heap byte buffers misalignment may occur on 32-bit systems
414            // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
415            // Note the GC will preserve alignment of the base address of the
416            // array
417            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8
418                    != longMisalignmentAtZero) {
419                fail("Heap byte buffer misaligned at index 0"
420                        + " for ref and primitive values "
421                        + longMisalignmentAtZero);
422            }
423        }
424
425        // Ensure test buffer is correctly aligned at index 0
426        if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
427            fail("Test input buffer not correctly aligned at index 0", b);
428
429        // Test misalignment values
430        for (int us : new int[]{1, 2, 4, 8}) {
431            for (int i = 0; i < us * 2; i++) {
432                int am = b.alignmentOffset(i, us);
433                int expectedAm = (longMisalignmentAtZero + i) % us;
434
435                if (am != expectedAm) {
436                    String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
437                    fail(String.format(f, i, us, am, expectedAm));
438                }
439            }
440        }
441
442        // Created aligned slice to test against
443        int ap = 8 - longMisalignmentAtZero;
444        int al = b.limit() - b.alignmentOffset(b.limit(), 8);
445        // Android-changed: Explicit casting due to @CovariantReturnType methods invisible to javac.
446        ByteBuffer ab = (ByteBuffer) b.position(ap).limit(al).
447                slice();
448        if (ab.limit() == 0) {
449            fail("Test input buffer not sufficiently sized to cover" +
450                    " an aligned region for all values", b);
451        }
452        if (ab.alignmentOffset(0, 8) != 0)
453            fail("Aligned test input buffer not correctly aligned at index 0", ab);
454
455        for (int us : new int[]{1, 2, 4, 8}) {
456            for (int p = 1; p < 16; p++) {
457                int l = ab.limit() - p;
458
459                // Android-changed: Explicit casting due to @CovariantReturnType methods.
460                ByteBuffer as = ((ByteBuffer) ab.slice().position(p).limit(l)).
461                        alignedSlice(us);
462
463                ck(as, 0, as.position());
464                ck(as, as.capacity(), as.limit());
465                if (b.isDirect() != as.isDirect())
466                    fail("Lost direction", as);
467                if (b.isReadOnly() != as.isReadOnly())
468                    fail("Lost read-only", as);
469
470                if (as.alignmentOffset(0, us) != 0)
471                    fail("Buffer not correctly aligned at index 0", as);
472
473                if (as.alignmentOffset(as.limit(), us) != 0)
474                    fail("Buffer not correctly aligned at limit", as);
475
476                int p_mod = ab.alignmentOffset(p, us);
477                int l_mod = ab.alignmentOffset(l, us);
478                // Round up position
479                p = (p_mod > 0) ? p + (us - p_mod) : p;
480                // Round down limit
481                l = l - l_mod;
482
483                int ec = l - p;
484                if (as.limit() != ec) {
485                    fail("Buffer capacity incorrect, expected: " + ec, as);
486                }
487            }
488        }
489
490        // mapped buffers
491        try {
492            for (MappedByteBuffer bb : mappedBuffers()) {
493                try {
494                    int offset = bb.alignmentOffset(1, 4);
495                    ck(bb, offset >= 0);
496                } catch (UnsupportedOperationException e) {
497                    System.out.println("Not applicable, UOE thrown: ");
498                }
499            }
500        } catch (IOException e) {
501            throw new UncheckedIOException(e);
502        }
503
504        // alignment identities
505        final int maxPow2 = 12;
506        ByteBuffer bb = ByteBuffer.allocateDirect(1 << maxPow2); // cap 4096
507
508        Random rnd = new Random();
509        long seed = rnd.nextLong();
510        rnd = new Random(seed);
511
512        for (int i = 0; i < 100; i++) {
513            // 1 == 2^0 <= unitSize == 2^k <= bb.capacity()/2
514            int unitSize = 1 << rnd.nextInt(maxPow2);
515            // 0 <= index < 2*unitSize
516            int index = rnd.nextInt(unitSize << 1);
517            int value = bb.alignmentOffset(index, unitSize);
518            try {
519                if (value < 0 || value >= unitSize) {
520                    throw new RuntimeException(value + " < 0 || " +
521                        value + " >= " + unitSize);
522                }
523                if (value <= index &&
524                    bb.alignmentOffset(index - value, unitSize) != 0)
525                    throw new RuntimeException("Identity 1");
526                if (bb.alignmentOffset(index + (unitSize - value),
527                    unitSize) != 0)
528                    throw new RuntimeException("Identity 2");
529            } catch (RuntimeException re) {
530                System.err.format("seed %d, index %d, unitSize %d, value %d%n",
531                    seed, index, unitSize, value);
532                throw re;
533            }
534        }
535    }
536
537    private static MappedByteBuffer[] mappedBuffers() throws IOException {
538        return new MappedByteBuffer[]{
539                createMappedBuffer(new byte[]{0, 1, 2, 3}),
540                createMappedBuffer(new byte[]{0, 1, 2, -3,
541                    45, 6, 7, 78, 3, -7, 6, 7, -128, 127}),
542        };
543    }
544
545    private static MappedByteBuffer createMappedBuffer(byte[] contents)
546        throws IOException {
547        Path tempFile = Files.createTempFile("mbb", null);
548        tempFile.toFile().deleteOnExit();
549        Files.write(tempFile, contents);
550        try (FileChannel fc = FileChannel.open(tempFile)) {
551            MappedByteBuffer map =
552                fc.map(FileChannel.MapMode.READ_ONLY, 0, contents.length);
553            map.load();
554            return map;
555        }
556    }
557#end[byte]
558
559    private static void fail(String problem,
560                             $Type$Buffer xb, $Type$Buffer yb,
561                             $type$ x, $type$ y) {
562        fail(problem + String.format(": x=%s y=%s", x, y), xb, yb);
563    }
564
565    private static void catchNullArgument(Buffer b, Runnable thunk) {
566        tryCatch(b, NullPointerException.class, thunk);
567    }
568
569    private static void catchIllegalArgument(Buffer b, Runnable thunk) {
570        tryCatch(b, IllegalArgumentException.class, thunk);
571    }
572
573    private static void catchReadOnlyBuffer(Buffer b, Runnable thunk) {
574        tryCatch(b, ReadOnlyBufferException.class, thunk);
575    }
576
577    private static void catchIndexOutOfBounds(Buffer b, Runnable thunk) {
578        tryCatch(b, IndexOutOfBoundsException.class, thunk);
579    }
580
581    private static void catchIndexOutOfBounds($type$[] t, Runnable thunk) {
582        tryCatch(t, IndexOutOfBoundsException.class, thunk);
583    }
584
585    private static void tryCatch(Buffer b, Class<?> ex, Runnable thunk) {
586        boolean caught = false;
587        try {
588            thunk.run();
589        } catch (Throwable x) {
590            if (ex.isAssignableFrom(x.getClass())) {
591                caught = true;
592            } else {
593                String s = x.getMessage();
594                if (s == null)
595                    s = x.getClass().getName();
596                fail(s + " not expected");
597            }
598        }
599        if (!caught) {
600            fail(ex.getName() + " not thrown", b);
601        }
602    }
603
604    private static void tryCatch($type$[] t, Class<?> ex, Runnable thunk) {
605        tryCatch($Type$Buffer.wrap(t), ex, thunk);
606    }
607
608    // Android-changed: Add @SuppressWarnings as the operation is tested to be reflexive.
609    @SuppressWarnings({"SelfComparison", "SelfEquals"})
610    public static void test(int level, final $Type$Buffer b, boolean direct) {
611
612        show(level, b);
613
614        if (direct != b.isDirect())
615            fail("Wrong direction", b);
616
617        // Gets and puts
618
619        relPut(b);
620        relGet(b);
621        absGet(b);
622        bulkGet(b);
623
624        absPut(b);
625        relGet(b);
626        absGet(b);
627        bulkGet(b);
628
629        bulkPutArray(b);
630        relGet(b);
631
632        bulkPutBuffer(b);
633        relGet(b);
634
635        absBulkPutArray(b);
636        absBulkGet(b);
637
638#if[char]
639
640        bulkPutString(b);
641        relGet(b);
642        b.position(1);
643        b.limit(7);
644        ck(b, b.toString().equals("bcdefg"));
645
646        // CharSequence ops
647
648        b.position(2);
649        ck(b, b.charAt(1), 'd');
650        CharBuffer c = b.subSequence(1, 4);
651        ck(c, c.capacity(), b.capacity());
652        ck(c, c.position(), b.position()+1);
653        ck(c, c.limit(), b.position()+4);
654        ck(c, b.subSequence(1, 4).toString().equals("def"));
655
656        // 4938424
657        b.position(4);
658        ck(b, b.charAt(1), 'f');
659        ck(b, b.subSequence(1, 3).toString().equals("fg"));
660
661        // String ops
662
663        // 7190219
664        b.clear();
665        int pos = b.position();
666        tryCatch(b, BufferOverflowException.class, () ->
667                b.put(String.valueOf(new char[b.capacity() + 1]), 0, b.capacity() + 1)
668            );
669        ck(b, b.position(), pos);
670        relGet(b);
671
672#end[char]
673
674        // Compact
675
676        relPut(b);
677        b.position(13);
678        b.compact();
679        b.flip();
680        relGet(b, 13);
681
682        // Exceptions
683
684        relPut(b);
685        b.limit(b.capacity() / 2);
686        b.position(b.limit());
687
688        tryCatch(b, BufferUnderflowException.class, () -> b.get());
689        tryCatch(b, BufferOverflowException.class, () -> b.put(($type$)42));
690        // The index must be non-negative and less than the buffer's limit.
691        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
692        catchIndexOutOfBounds(b, () -> b.get(-1));
693        catchIndexOutOfBounds(b, () -> b.put(b.limit(), ($type$)42));
694        tryCatch(b, InvalidMarkException.class,
695                // Android-changed: Explicit casting due to @CovariantReturnType methods.
696                // () -> b.position(0).mark().compact().reset());
697                () -> (($Type$Buffer) b.position(0).mark()).compact().reset());
698
699        try {
700            b.position(b.limit() + 1);
701            fail("IllegalArgumentException expected for position beyond limit");
702        } catch (IllegalArgumentException e) {
703            if (e.getMessage() == null) {
704                fail("Non-null IllegalArgumentException message expected for"
705                     + " position beyond limit");
706            }
707        }
708
709        try {
710            b.position(-1);
711            fail("IllegalArgumentException expected for negative position");
712        } catch (IllegalArgumentException e) {
713            if (e.getMessage() == null) {
714                fail("Non-null IllegalArgumentException message expected for"
715                     + " negative position");
716            }
717        }
718
719        try {
720            b.limit(b.capacity() + 1);
721            fail("IllegalArgumentException expected for limit beyond capacity");
722        } catch (IllegalArgumentException e) {
723            if (e.getMessage() == null) {
724                fail("Non-null IllegalArgumentException message expected for"
725                     + " limit beyond capacity");
726            }
727        }
728
729        try {
730            b.limit(-1);
731            fail("IllegalArgumentException expected for negative limit");
732        } catch (IllegalArgumentException e) {
733            if (e.getMessage() == null) {
734                fail("Non-null IllegalArgumentException message expected for"
735                     + " negative limit");
736            }
737        }
738
739        // Exceptions in absolute bulk and slice operations
740
741        catchNullArgument(b, () -> b.get(7, null, 0, 42));
742        catchNullArgument(b, () -> b.put(7, ($type$[])null, 0, 42));
743
744        $type$[] tmpa = new $type$[42];
745        catchIndexOutOfBounds(b, () -> b.get(7, tmpa, -1, 42));
746        catchIndexOutOfBounds(b, () -> b.get(7, tmpa, 42, 1));
747        catchIndexOutOfBounds(b, () -> b.get(7, tmpa, 41, -1));
748        catchIndexOutOfBounds(b, () -> b.get(-1, tmpa, 0, 1));
749        catchIndexOutOfBounds(b, () -> b.get(b.limit(), tmpa, 0, 1));
750        catchIndexOutOfBounds(b, () -> b.get(b.limit() - 41, tmpa, 0, 42));
751
752        catchIndexOutOfBounds(b, () -> b.put(7, tmpa, -1, 42));
753        catchIndexOutOfBounds(b, () -> b.put(7, tmpa, 42, 1));
754        catchIndexOutOfBounds(b, () -> b.put(7, tmpa, 41, -1));
755        catchIndexOutOfBounds(b, () -> b.put(-1, tmpa, 0, 1));
756        catchIndexOutOfBounds(b, () -> b.put(b.limit(), tmpa, 0, 1));
757        catchIndexOutOfBounds(b, () -> b.put(b.limit() - 41, tmpa, 0, 42));
758
759        catchIndexOutOfBounds(b, () -> b.slice(-1, 7));
760        catchIndexOutOfBounds(b, () -> b.slice(b.limit() + 1, 7));
761        catchIndexOutOfBounds(b, () -> b.slice(0, -1));
762        catchIndexOutOfBounds(b, () -> b.slice(7, b.limit() - 7 + 1));
763
764        // Values
765
766        b.clear();
767        b.put(($type$)0);
768        b.put(($type$)-1);
769        b.put(($type$)1);
770        b.put($Fulltype$.MAX_VALUE);
771        b.put($Fulltype$.MIN_VALUE);
772#if[float]
773        b.put(-Float.MAX_VALUE);
774        b.put(-Float.MIN_VALUE);
775        b.put(Float.NEGATIVE_INFINITY);
776        b.put(Float.POSITIVE_INFINITY);
777        b.put(Float.NaN);
778        b.put(0.91697687f);             // Changes value if incorrectly swapped
779#end[float]
780#if[double]
781        b.put(-Double.MAX_VALUE);
782        b.put(-Double.MIN_VALUE);
783        b.put(Double.NEGATIVE_INFINITY);
784        b.put(Double.POSITIVE_INFINITY);
785        b.put(Double.NaN);
786        b.put(0.5121609353879392);      // Changes value if incorrectly swapped
787#end[double]
788
789        b.flip();
790        ck(b, b.get(), 0);
791        ck(b, b.get(), ($type$)-1);
792        ck(b, b.get(), 1);
793        ck(b, b.get(), $Fulltype$.MAX_VALUE);
794        ck(b, b.get(), $Fulltype$.MIN_VALUE);
795
796#if[float]
797        $type$ v;
798        ck(b, b.get(), -Float.MAX_VALUE);
799        ck(b, b.get(), -Float.MIN_VALUE);
800        ck(b, b.get(), Float.NEGATIVE_INFINITY);
801        ck(b, b.get(), Float.POSITIVE_INFINITY);
802        if (Float.floatToRawIntBits(v = b.get()) !=
803            Float.floatToRawIntBits(Float.NaN)) {
804            fail(b, (long)Float.NaN, (long)v);
805        }
806        ck(b, b.get(), 0.91697687f);
807#end[float]
808#if[double]
809        $type$ v;
810        ck(b, b.get(), -Double.MAX_VALUE);
811        ck(b, b.get(), -Double.MIN_VALUE);
812        ck(b, b.get(), Double.NEGATIVE_INFINITY);
813        ck(b, b.get(), Double.POSITIVE_INFINITY);
814        if (Double.doubleToRawLongBits(v = b.get())
815            != Double.doubleToRawLongBits(Double.NaN)) {
816            fail(b, (long)Double.NaN, (long)v);
817        }
818        ck(b, b.get(), 0.5121609353879392);
819#end[double]
820
821
822        // Comparison
823        b.rewind();
824        $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity());
825        b2.put(b);
826        b2.flip();
827        b.position(2);
828        b2.position(2);
829        if (!b.equals(b2)) {
830            for (int i = 2; i < b.limit(); i++) {
831                $type$ x = b.get(i);
832                $type$ y = b2.get(i);
833                if (x != y
834#if[double]
835                    || Double.compare(x, y) != 0
836#end[double]
837#if[float]
838                    || Float.compare(x, y) != 0
839#end[float]
840                    ) {
841                    out.println("[" + i + "] " + x + " != " + y);
842                }
843            }
844            fail("Identical buffers not equal", b, b2);
845        }
846        if (b.compareTo(b2) != 0) {
847            fail("Comparison to identical buffer != 0", b, b2);
848        }
849        b.limit(b.limit() + 1);
850        b.position(b.limit() - 1);
851        b.put(($type$)99);
852        b.rewind();
853        b2.rewind();
854        if (b.equals(b2))
855            fail("Non-identical buffers equal", b, b2);
856        if (b.compareTo(b2) <= 0)
857            fail("Comparison to shorter buffer <= 0", b, b2);
858        b.limit(b.limit() - 1);
859
860        b.put(2, ($type$)42);
861        if (b.equals(b2))
862            fail("Non-identical buffers equal", b, b2);
863        if (b.compareTo(b2) <= 0)
864            fail("Comparison to lesser buffer <= 0", b, b2);
865
866        // Check equals and compareTo with interesting values
867        for ($type$ x : VALUES) {
868            $Type$Buffer xb = $Type$Buffer.wrap(new $type$[] { x });
869            if (xb.compareTo(xb) != 0) {
870                fail("compareTo not reflexive", xb, xb, x, x);
871            }
872            if (!xb.equals(xb)) {
873                fail("equals not reflexive", xb, xb, x, x);
874            }
875            for ($type$ y : VALUES) {
876                $Type$Buffer yb = $Type$Buffer.wrap(new $type$[] { y });
877                if (xb.compareTo(yb) != - yb.compareTo(xb)) {
878                    fail("compareTo not anti-symmetric",
879                         xb, yb, x, y);
880                }
881                if ((xb.compareTo(yb) == 0) != xb.equals(yb)) {
882                    fail("compareTo inconsistent with equals",
883                         xb, yb, x, y);
884                }
885                if (xb.compareTo(yb) != $Fulltype$.compare(x, y)) {
886#if[float]
887                    if (x == 0.0 && y == 0.0) continue;
888#end[float]
889#if[double]
890                    if (x == 0.0 && y == 0.0) continue;
891#end[double]
892                    fail("Incorrect results for $Type$Buffer.compareTo",
893                         xb, yb, x, y);
894                }
895
896#if[float]
897		// Android-changed: fix issue flagged by error prone (x != x) instead of isNan(x).
898                if (!(Float.isNaN(x) && Float.isNaN(y))) {
899#end[float]
900#if[double]
901		// Android-changed: fix issue flagged by error prone (x != x) instead of isNan(x).
902                if (!(Double.isNaN(x) && Double.isNaN(y))) {
903#end[double]
904                if (xb.equals(yb) != (x == y)) {
905                    fail("Incorrect results for $Type$Buffer.equals",
906                         xb, yb, x, y);
907                }
908
909#if[float]
910                }
911#end[float]
912#if[double]
913                }
914#end[double]
915            }
916        }
917
918        // Sub, dup
919
920        relPut(b);
921        relGet(b.duplicate());
922        b.position(13);
923        relGet(b.duplicate(), 13);
924        relGet(b.duplicate().slice(), 13);
925        relGet(b.slice(), 13);
926        relGet(b.slice().duplicate(), 13);
927
928        // Slice
929
930        b.position(5);
931        $Type$Buffer sb = b.slice();
932        checkSlice(b, sb);
933        b.position(0);
934        $Type$Buffer sb2 = sb.slice();
935        checkSlice(sb, sb2);
936
937        if (!sb.equals(sb2))
938            fail("Sliced slices do not match", sb, sb2);
939        if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) {
940            fail("Array offsets do not match: "
941                 + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2);
942        }
943
944        int bPos = b.position();
945        int bLim = b.limit();
946
947        b.position(7);
948        b.limit(42);
949        $Type$Buffer rsb = b.slice();
950        b.position(0);
951        b.limit(b.capacity());
952        $Type$Buffer asb = b.slice(7, 35);
953        checkSlice(rsb, asb);
954
955        b.position(bPos);
956        b.limit(bLim);
957
958#if[byte]
959
960        // Views
961
962        b.clear();
963        b.order(ByteOrder.BIG_ENDIAN);
964        testViews(level + 1, b, direct);
965
966        for (int i = 1; i <= 9; i++) {
967            b.position(i);
968            show(level + 1, b);
969            testViews(level + 2, b, direct);
970        }
971
972        b.position(0);
973        b.order(ByteOrder.LITTLE_ENDIAN);
974        testViews(level + 1, b, direct);
975
976        // Heterogeneous accessors
977
978        b.order(ByteOrder.BIG_ENDIAN);
979        for (int i = 0; i <= 9; i++) {
980            b.position(i);
981            testHet(level + 1, b);
982        }
983        b.order(ByteOrder.LITTLE_ENDIAN);
984        b.position(3);
985        testHet(level + 1, b);
986
987#end[byte]
988
989        // Read-only views
990
991        b.rewind();
992        final $Type$Buffer rb = b.asReadOnlyBuffer();
993        if (!b.equals(rb))
994            fail("Buffer not equal to read-only view", b, rb);
995        show(level + 1, rb);
996
997        catchReadOnlyBuffer(b, () -> relPut(rb));
998        catchReadOnlyBuffer(b, () -> absPut(rb));
999        catchReadOnlyBuffer(b, () -> bulkPutArray(rb));
1000        catchReadOnlyBuffer(b, () -> bulkPutBuffer(rb));
1001        catchReadOnlyBuffer(b, () -> absBulkPutArray(rb));
1002
1003        // put($Type$Buffer) should not change source position
1004        final $Type$Buffer src = $Type$Buffer.allocate(1);
1005        catchReadOnlyBuffer(b, () -> rb.put(src));
1006        ck(src, src.position(), 0);
1007
1008        catchReadOnlyBuffer(b, () -> rb.compact());
1009
1010#if[byte]
1011
1012        catchReadOnlyBuffer(b, () -> rb.putChar((char)1));
1013        catchReadOnlyBuffer(b, () -> rb.putChar(0, (char)1));
1014        catchReadOnlyBuffer(b, () -> rb.putShort((short)1));
1015        catchReadOnlyBuffer(b, () -> rb.putShort(0, (short)1));
1016        catchReadOnlyBuffer(b, () -> rb.putInt(1));
1017        catchReadOnlyBuffer(b, () -> rb.putInt(0, 1));
1018        catchReadOnlyBuffer(b, () -> rb.putLong((long)1));
1019        catchReadOnlyBuffer(b, () -> rb.putLong(0, (long)1));
1020        catchReadOnlyBuffer(b, () -> rb.putFloat((float)1));
1021        catchReadOnlyBuffer(b, () -> rb.putFloat(0, (float)1));
1022        catchReadOnlyBuffer(b, () -> rb.putDouble((double)1));
1023        catchReadOnlyBuffer(b, () -> rb.putDouble(0, (double)1));
1024
1025#end[byte]
1026
1027#if[char]
1028
1029        // 7199551
1030        catchReadOnlyBuffer(b, () -> rb.put(new String(new char[rb.remaining() + 1])));
1031        catchReadOnlyBuffer(b, () -> rb.append(new String(new char[rb.remaining() + 1])));
1032
1033#end[char]
1034
1035        if (rb.getClass().getName().startsWith("java.nio.Heap")) {
1036            catchReadOnlyBuffer(b, () -> rb.array());
1037            catchReadOnlyBuffer(b, () -> rb.arrayOffset());
1038            if (rb.hasArray()) {
1039                fail("Read-only heap buffer's backing array is accessible", rb);
1040            }
1041        }
1042
1043        // Bulk puts from read-only buffers
1044
1045        b.clear();
1046        rb.rewind();
1047        b.put(rb);
1048
1049#if[byte]
1050        // For byte buffers, test both the direct and non-direct cases
1051        $Type$Buffer ob
1052            = (b.isDirect()
1053               ? $Type$Buffer.allocate(rb.capacity())
1054               : $Type$Buffer.allocateDirect(rb.capacity()));
1055        rb.rewind();
1056        ob.put(rb);
1057#end[byte]
1058
1059        relPut(b);                       // Required by testViews
1060
1061#if[byte]
1062        // Test alignment
1063
1064        testAlign(b, direct);
1065#end[byte]
1066    }
1067
1068#if[char]
1069
1070    private static void testStr() {
1071        final String s = "abcdefghijklm";
1072        int start = 3;
1073        int end = 9;
1074        final CharBuffer b = CharBuffer.wrap(s, start, end);
1075        show(0, b);
1076        ck(b, b.toString().equals(s.substring(start, end)));
1077        ck(b, b.toString().equals("defghi"));
1078        ck(b, b.isReadOnly());
1079        catchReadOnlyBuffer(b, () -> b.put('x'));
1080        ck(b, start, b.position());
1081        ck(b, end, b.limit());
1082        ck(b, s.length(), b.capacity());
1083        b.position(6);
1084        ck(b, b.subSequence(0,3).toString().equals("ghi"));
1085
1086        // absolute bulk get
1087        char[] c = new char[end + 1 - (start - 1) + 1]; // [start - 1, end + 1]
1088        b.limit(end + 2);
1089        b.get(start - 1, c, 0, c.length);
1090        for (int i = 0; i < c.length; i++)
1091            ck(b, c[i], s.charAt(start - 1 + i));
1092
1093        // The index, relative to the position, must be non-negative and
1094        // smaller than remaining().
1095        catchIndexOutOfBounds(b, () -> b.charAt(-1));
1096        catchIndexOutOfBounds(b, () -> b.charAt(b.remaining()));
1097        // The index must be non-negative and less than the buffer's limit.
1098        catchIndexOutOfBounds(b, () -> b.get(b.limit()));
1099        catchIndexOutOfBounds(b, () -> b.get(-1));
1100        // The start must be non-negative and no larger than remaining().
1101        catchIndexOutOfBounds(b, () -> b.subSequence(-1, b.remaining()));
1102        catchIndexOutOfBounds(b, () -> b.subSequence(b.remaining() + 1, b.remaining()));
1103
1104        // The end must be no smaller than start and no larger than
1105        // remaining().
1106        catchIndexOutOfBounds(b, () -> b.subSequence(2, 1));
1107        catchIndexOutOfBounds(b, () -> b.subSequence(0, b.remaining() + 1));
1108
1109        // The offset must be non-negative and no larger than <array.length>.
1110        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, -1, s.length()));
1111        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, s.length() + 1, s.length()));
1112        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, 1, 0));
1113        catchIndexOutOfBounds(b, () -> $Type$Buffer.wrap(s, 0, s.length() + 1));
1114    }
1115
1116#end[char]
1117
1118    public static void test(final $type$ [] ba) {
1119        int offset = 47;
1120        int length = 900;
1121        final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length);
1122        show(0, b);
1123        ck(b, b.capacity(), ba.length);
1124        ck(b, b.position(), offset);
1125        ck(b, b.limit(), offset + length);
1126
1127        // The offset must be non-negative and no larger than <array.length>.
1128        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, -1, ba.length));
1129        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, ba.length + 1, ba.length));
1130        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, 0, -1));
1131        catchIndexOutOfBounds(ba, () -> $Type$Buffer.wrap(ba, 0, ba.length + 1));
1132
1133        // A NullPointerException will be thrown if the array is null.
1134        tryCatch(ba, NullPointerException.class,
1135                () -> $Type$Buffer.wrap(($type$ []) null, 0, 5));
1136        tryCatch(ba, NullPointerException.class,
1137                () -> $Type$Buffer.wrap(($type$ []) null));
1138    }
1139
1140    private static void testAllocate() {
1141        // An IllegalArgumentException will be thrown for negative capacities.
1142        catchIllegalArgument((Buffer) null, () -> $Type$Buffer.allocate(-1));
1143        try {
1144            $Type$Buffer.allocate(-1);
1145        } catch (IllegalArgumentException e) {
1146            if (e.getMessage() == null) {
1147                fail("Non-null IllegalArgumentException message expected for"
1148                     + " attempt to allocate negative capacity buffer");
1149            }
1150        }
1151#if[byte]
1152        catchIllegalArgument((Buffer) null, () -> $Type$Buffer.allocateDirect(-1));
1153        try {
1154            $Type$Buffer.allocateDirect(-1);
1155        } catch (IllegalArgumentException e) {
1156            if (e.getMessage() == null) {
1157                fail("Non-null IllegalArgumentException message expected for"
1158                     + " attempt to allocate negative capacity direct buffer");
1159            }
1160        }
1161#end[byte]
1162    }
1163
1164    public static void testToString() {
1165        final int cap = 10;
1166
1167#if[byte]
1168        $Type$Buffer direct1 = $Type$Buffer.allocateDirect(cap);
1169        if (!direct1.toString().equals(Basic.toString(direct1))) {
1170           fail("Direct buffer toString is incorrect: "
1171                  + direct1.toString() + " vs " + Basic.toString(direct1));
1172        }
1173#end[byte]
1174
1175#if[!char]
1176        $Type$Buffer nondirect1 = $Type$Buffer.allocate(cap);
1177        if (!nondirect1.toString().equals(Basic.toString(nondirect1))) {
1178           fail("Heap buffer toString is incorrect: "
1179                  + nondirect1.toString() + " vs " + Basic.toString(nondirect1));
1180        }
1181#end[!char]
1182    }
1183
1184    public static void test() {
1185        testAllocate();
1186        test(0, $Type$Buffer.allocate(7 * 1024), false);
1187        test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false);
1188        test(new $type$[1024]);
1189#if[byte]
1190        $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024);
1191        for (b.position(0); b.position() < b.limit(); )
1192            ck(b, b.get(), 0);
1193        test(0, b, true);
1194#end[byte]
1195#if[char]
1196        testStr();
1197#end[char]
1198
1199        callReset($Type$Buffer.allocate(10));
1200
1201#if[byte]
1202#else[byte]
1203        putBuffer();
1204#end[byte]
1205
1206        testToString();
1207
1208        // Android-added: Add API coverage for get(), put().
1209        testGetPutArrayWithIndex();
1210#if[!byte]
1211        testPutBuffer();
1212#end[!byte]
1213    }
1214
1215    // BEGIN Android-added: Add API coverage for get(), put().
1216    private static void testGetPutArrayWithIndex() {
1217        $Type$Buffer buf = $Type$Buffer.allocate(16);
1218        $type$ firstElement = 11, secondElement = 12;
1219        buf.put(firstElement);
1220        buf.put(secondElement);
1221        buf.position(0);
1222        $type$[] arr = new $type$[] { 4, 3, 2, 1 };
1223        buf.put(2, arr);
1224        $type$[] actual = new $type$[4];
1225        buf.get(2, actual);
1226        assertEquals(actual, arr);
1227        buf.get(0, actual);
1228        assertEquals(actual, new $type$[] {firstElement, secondElement, 4, 3});
1229    }
1230#if[!byte]
1231    private static void testPutBuffer() {
1232        Supplier<$Type$Buffer>[] newBuffers = new Supplier[] {
1233                () -> $Type$Buffer.allocate(512),
1234                () -> $Type$Buffer.allocate(512).slice(100, 412),
1235                () -> ByteBuffer.allocate(512 * $Fulltype$.BYTES).order(ByteOrder.LITTLE_ENDIAN).as$Type$Buffer(),
1236                () -> ByteBuffer.allocate(512 * $Fulltype$.BYTES).order(ByteOrder.BIG_ENDIAN).as$Type$Buffer(),
1237                () -> ByteBuffer.allocateDirect(512 * $Fulltype$.BYTES).order(ByteOrder.LITTLE_ENDIAN).as$Type$Buffer(),
1238                () -> ByteBuffer.allocateDirect(512 * $Fulltype$.BYTES).order(ByteOrder.BIG_ENDIAN).as$Type$Buffer(),
1239                () -> ByteBuffer.allocateDirect(512 * $Fulltype$.BYTES).as$Type$Buffer().slice(100, 412),
1240                () -> ((ByteBuffer) ByteBuffer.allocateDirect(512 * $Fulltype$.BYTES)
1241                        .order(ByteOrder.LITTLE_ENDIAN).position(100)).as$Type$Buffer(),
1242                () -> ((ByteBuffer) ByteBuffer.allocateDirect(512 * $Fulltype$.BYTES)
1243                        .order(ByteOrder.BIG_ENDIAN).position(100)).as$Type$Buffer(),
1244        };
1245
1246        $type$[] samples = new $type$[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1247        for (var newSrc : newBuffers) {
1248            for (var newDst : newBuffers) {
1249                $type$[] out = new $type$[10];
1250                $Type$Buffer src = newSrc.get();
1251                src.put(samples);
1252                src.get(0, out);
1253                assertEquals(out, samples);
1254                assertEquals(src.get(10), ($type$) 0);
1255                src.limit(10);
1256                src.rewind();
1257
1258                out = new $type$[10];
1259                $Type$Buffer dst = newDst.get();
1260                dst.put(src);
1261                dst.get(0, out);
1262                assertEquals(out, samples);
1263                dst.rewind();
1264
1265                dst.put(6, src, 1, 2);
1266                assertEquals(dst.get(6), ($type$) 1);
1267                assertEquals(dst.get(7), ($type$) 2);
1268                assertEquals(dst.get(8), ($type$) 8);
1269                assertEquals(dst.get(10), ($type$) 0);
1270
1271                dst.put(12, src, 2, 2);
1272                out = new $type$[5];
1273                dst.get(10, out);
1274                assertEquals(out, new $type$[] {0, 0, 2, 3, 0});
1275
1276            }
1277        }
1278    }
1279#end[!byte]
1280    // END Android-added: Add API coverage for get(), put().
1281}
1282