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