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