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 }