1 /*
   2  * Copyright (c) 2016, 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 /* @test
  25  * @summary Binary data and view tests for byte buffers
  26  * @bug 8159257
  27  * @run testng ByteBufferViews
  28  */
  29 
  30 import org.testng.annotations.DataProvider;
  31 import org.testng.annotations.Test;
  32 
  33 import java.nio.Buffer;
  34 import java.nio.ByteBuffer;
  35 import java.nio.ByteOrder;
  36 import java.nio.CharBuffer;
  37 import java.nio.DoubleBuffer;
  38 import java.nio.FloatBuffer;
  39 import java.nio.IntBuffer;
  40 import java.nio.LongBuffer;
  41 import java.nio.ShortBuffer;
  42 import java.util.List;
  43 import java.util.Map;
  44 import java.util.function.Function;
  45 import java.util.function.IntFunction;
  46 import java.util.function.IntUnaryOperator;
  47 import java.util.function.UnaryOperator;
  48 import java.util.stream.Collectors;
  49 
  50 import static org.testng.Assert.*;
  51 
  52 public class ByteBufferViews {
  53     static final int SIZE = 32;
  54 
  55     // List of buffer allocator functions
  56     static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_ALLOCATE_FUNCTIONS = List.of(
  57             // Heap
  58             Map.entry("ByteBuffer.allocate(ba)",
  59                       size -> ByteBuffer.allocate(size)),
  60             // Aligned
  61             Map.entry("ByteBuffer.allocate(size).position(8)",
  62                       size -> ByteBuffer.allocate(size).position(8)),
  63             Map.entry("ByteBuffer.allocate(size).position(8).slice()",
  64                       size -> ByteBuffer.allocate(size).position(8).slice()),
  65             Map.entry("ByteBuffer.allocate(size).position(8).slice().duplicate()",
  66                       size -> ByteBuffer.allocate(size).position(8).slice().duplicate()),
  67             // Unaligned
  68             Map.entry("ByteBuffer.allocate(size).position(1)",
  69                       size -> ByteBuffer.allocate(size).position(1)),
  70             Map.entry("ByteBuffer.allocate(size).position(1).slice()",
  71                       size -> ByteBuffer.allocate(size).position(1).slice()),
  72             Map.entry("ByteBuffer.allocate(size).position(1).slice().duplicate()",
  73                       size -> ByteBuffer.allocate(size).position(1).slice().duplicate()),
  74 
  75             // Off-heap
  76             Map.entry("ByteBuffer.allocateDirect(size)",
  77                       size -> ByteBuffer.allocateDirect(size)),
  78             // Aligned
  79             Map.entry("ByteBuffer.allocateDirect(size).position(8)",
  80                       size -> ByteBuffer.allocateDirect(size).position(8)),
  81             Map.entry("ByteBuffer.allocateDirect(size).position(8).slice()",
  82                       size -> ByteBuffer.allocateDirect(size).position(8).slice()),
  83             Map.entry("ByteBuffer.allocateDirect(size).position(8).slice().duplicate()",
  84                       size -> ByteBuffer.allocateDirect(size).position(8).slice().duplicate()),
  85             // Unaligned
  86             Map.entry("ByteBuffer.allocateDirect(size).position(1)",
  87                       size -> ByteBuffer.allocateDirect(size).position(1)),
  88             Map.entry("ByteBuffer.allocateDirect(size).position(1).slice()",
  89                       size -> ByteBuffer.allocateDirect(size).position(1).slice()),
  90             Map.entry("ByteBuffer.allocateDirect(size).position(1).slice().duplicate()",
  91                       size -> ByteBuffer.allocateDirect(size).position(1).slice().duplicate())
  92     );
  93 
  94     // List of buffer byte order functions
  95     static final List<Map.Entry<String, UnaryOperator<ByteBuffer>>> BYTE_BUFFER_ORDER_FUNCTIONS = List.of(
  96             Map.entry("order(ByteOrder.BIG_ENDIAN)",
  97                       (ByteBuffer bb) -> bb.order(ByteOrder.BIG_ENDIAN)),
  98             Map.entry("order(ByteOrder.LITTLE_ENDIAN)",
  99                       (ByteBuffer bb) -> bb.order(ByteOrder.LITTLE_ENDIAN))
 100     );
 101 
 102     // Produce a composition of allocation and byte order buffer functions
 103     static List<Map.Entry<String, IntFunction<ByteBuffer>>> composeBufferFunctions(
 104             List<Map.Entry<String, IntFunction<ByteBuffer>>> af,
 105             List<Map.Entry<String, UnaryOperator<ByteBuffer>>> of) {
 106         return af.stream().flatMap(afe -> of.stream().
 107                 map(ofe -> {
 108                     String s = afe.getKey() + "." + ofe.getKey();
 109                     IntFunction<ByteBuffer> f = size -> ofe.getValue().
 110                             apply(afe.getValue().apply(size));
 111                     return Map.entry(s, f);
 112                 })
 113         ).collect(Collectors.toList());
 114     }
 115 
 116     // List of buffer allocator functions to test
 117     static final List<Map.Entry<String, IntFunction<ByteBuffer>>> BYTE_BUFFER_FUNCTIONS =
 118             composeBufferFunctions(BYTE_BUFFER_ALLOCATE_FUNCTIONS, BYTE_BUFFER_ORDER_FUNCTIONS);
 119 
 120     // Creates a cross product of test arguments for
 121     // buffer allocator functions and buffer view functions
 122     static Object[][] product(List<? extends Map.Entry<String, ?>> la,
 123                               List<? extends Map.Entry<String, ?>> lb) {
 124         return la.stream().flatMap(lae -> lb.stream().
 125                 map(lbe -> List.of(
 126                         lae.getKey() + " -> " + lbe.getKey(),
 127                         lae.getValue(),
 128                         lbe.getValue()).toArray()
 129                 )).toArray(Object[][]::new);
 130     }
 131 
 132     static void assertValues(int i, Object bValue, Object bbValue, ByteBuffer bb) {
 133         if (!bValue.equals(bbValue)) {
 134             fail(String.format("Values %s and %s differ at index %d for %s",
 135                                bValue, bbValue, i, bb));
 136         }
 137     }
 138 
 139     static void assertValues(int i, Object bbValue, Object bvValue, ByteBuffer bb, Buffer bv) {
 140         if (!bbValue.equals(bvValue)) {
 141             fail(String.format("Values %s and %s differ at index %d for %s and %s",
 142                                bbValue, bvValue, i, bb, bv));
 143         }
 144     }
 145 
 146     static ByteBuffer allocate(IntFunction<ByteBuffer> f) {
 147         return allocate(f, i -> i);
 148     }
 149 
 150     static ByteBuffer allocate(IntFunction<ByteBuffer> f, IntUnaryOperator o) {
 151         return fill(f.apply(SIZE), o);
 152     }
 153 
 154     static ByteBuffer fill(ByteBuffer bb, IntUnaryOperator o) {
 155         for (int i = 0; i < bb.limit(); i++) {
 156             bb.put(i, (byte) o.applyAsInt(i));
 157         }
 158         return bb;
 159     }
 160 
 161 
 162     @DataProvider
 163     public static Object[][] shortViewProvider() {
 164         List<Map.Entry<String, Function<ByteBuffer, ShortBuffer>>> bfs = List.of(
 165                 Map.entry("bb.asShortBuffer()",
 166                           bb -> bb.asShortBuffer()),
 167                 Map.entry("bb.asShortBuffer().slice()",
 168                           bb -> bb.asShortBuffer().slice()),
 169                 Map.entry("bb.asShortBuffer().slice().duplicate()",
 170                           bb -> bb.asShortBuffer().slice().duplicate())
 171         );
 172 
 173         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 174     }
 175 
 176     @Test(dataProvider = "shortViewProvider")
 177     public void testShortGet(String desc, IntFunction<ByteBuffer> fbb,
 178                              Function<ByteBuffer, ShortBuffer> fbi) {
 179         ByteBuffer bb = allocate(fbb);
 180         ShortBuffer vb = fbi.apply(bb);
 181         int o = bb.position();
 182 
 183         for (int i = 0; i < vb.limit(); i++) {
 184             short fromBytes = getShortFromBytes(bb, o + i * 2);
 185             short fromMethodView = bb.getShort(o + i * 2);
 186             assertValues(i, fromBytes, fromMethodView, bb);
 187 
 188             short fromBufferView = vb.get(i);
 189             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 190         }
 191 
 192         for (int i = 0; i < vb.limit(); i++) {
 193             short v = getShortFromBytes(bb, o + i * 2);
 194             short a = bb.getShort();
 195             assertValues(i, v, a, bb);
 196 
 197             short b = vb.get();
 198             assertValues(i, a, b, bb, vb);
 199         }
 200 
 201     }
 202 
 203     @Test(dataProvider = "shortViewProvider")
 204     public void testShortPut(String desc, IntFunction<ByteBuffer> fbb,
 205                              Function<ByteBuffer, ShortBuffer> fbi) {
 206         ByteBuffer bbfilled = allocate(fbb);
 207         ByteBuffer bb = allocate(fbb, i -> 0);
 208         ShortBuffer vb = fbi.apply(bb);
 209         int o = bb.position();
 210 
 211         for (int i = 0; i < vb.limit(); i++) {
 212             short fromFilled = bbfilled.getShort(o + i * 2);
 213 
 214             vb.put(i, fromFilled);
 215             short fromMethodView = bb.getShort(o + i * 2);
 216             assertValues(i, fromFilled, fromMethodView, bb, vb);
 217         }
 218 
 219         for (int i = 0; i < vb.limit(); i++) {
 220             short fromFilled = bbfilled.getShort(o + i * 2);
 221 
 222             vb.put(fromFilled);
 223             short fromMethodView = bb.getShort();
 224             assertValues(i, fromFilled, fromMethodView, bb, vb);
 225         }
 226 
 227 
 228         fill(bb, i -> 0);
 229         bb.clear().position(o);
 230         vb.clear();
 231 
 232         for (int i = 0; i < vb.limit(); i++) {
 233             short fromFilled = bbfilled.getShort(o + i * 2);
 234 
 235             bb.putShort(o + i * 2, fromFilled);
 236             short fromBufferView = vb.get(i);
 237             assertValues(i, fromFilled, fromBufferView, bb, vb);
 238         }
 239 
 240         for (int i = 0; i < vb.limit(); i++) {
 241             short fromFilled = bbfilled.getShort(o + i * 2);
 242 
 243             bb.putShort(fromFilled);
 244             short fromBufferView = vb.get();
 245             assertValues(i, fromFilled, fromBufferView, bb, vb);
 246         }
 247     }
 248 
 249     static short getShortFromBytes(ByteBuffer bb, int i) {
 250         int a = bb.get(i) & 0xFF;
 251         int b = bb.get(i + 1) & 0xFF;
 252 
 253         if (bb.order() == ByteOrder.BIG_ENDIAN) {
 254             return (short) ((a << 8) | b);
 255         }
 256         else {
 257             return (short) ((b << 8) | a);
 258         }
 259     }
 260 
 261     @DataProvider
 262     public static Object[][] charViewProvider() {
 263         List<Map.Entry<String, Function<ByteBuffer, CharBuffer>>> bfs = List.of(
 264                 Map.entry("bb.asCharBuffer()",
 265                           bb -> bb.asCharBuffer()),
 266                 Map.entry("bb.asCharBuffer().slice()",
 267                           bb -> bb.asCharBuffer().slice()),
 268                 Map.entry("bb.asCharBuffer().slice().duplicate()",
 269                           bb -> bb.asCharBuffer().slice().duplicate())
 270         );
 271 
 272         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 273     }
 274 
 275     @Test(dataProvider = "charViewProvider")
 276     public void testCharGet(String desc, IntFunction<ByteBuffer> fbb,
 277                             Function<ByteBuffer, CharBuffer> fbi) {
 278         ByteBuffer bb = allocate(fbb);
 279         CharBuffer vb = fbi.apply(bb);
 280         int o = bb.position();
 281 
 282         for (int i = 0; i < vb.limit(); i++) {
 283             char fromBytes = getCharFromBytes(bb, o + i * 2);
 284             char fromMethodView = bb.getChar(o + i * 2);
 285             assertValues(i, fromBytes, fromMethodView, bb);
 286 
 287             char fromBufferView = vb.get(i);
 288             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 289         }
 290 
 291         for (int i = 0; i < vb.limit(); i++) {
 292             char fromBytes = getCharFromBytes(bb, o + i * 2);
 293             char fromMethodView = bb.getChar();
 294             assertValues(i, fromBytes, fromMethodView, bb);
 295 
 296             char fromBufferView = vb.get();
 297             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 298         }
 299 
 300     }
 301 
 302     @Test(dataProvider = "charViewProvider")
 303     public void testCharPut(String desc, IntFunction<ByteBuffer> fbb,
 304                             Function<ByteBuffer, CharBuffer> fbi) {
 305         ByteBuffer bbfilled = allocate(fbb);
 306         ByteBuffer bb = allocate(fbb, i -> 0);
 307         CharBuffer vb = fbi.apply(bb);
 308         int o = bb.position();
 309 
 310         for (int i = 0; i < vb.limit(); i++) {
 311             char fromFilled = bbfilled.getChar(o + i * 2);
 312 
 313             vb.put(i, fromFilled);
 314             char fromMethodView = bb.getChar(o + i * 2);
 315             assertValues(i, fromFilled, fromMethodView, bb, vb);
 316         }
 317 
 318         for (int i = 0; i < vb.limit(); i++) {
 319             char fromFilled = bbfilled.getChar(o + i * 2);
 320 
 321             vb.put(fromFilled);
 322             char fromMethodView = bb.getChar();
 323             assertValues(i, fromFilled, fromMethodView, bb, vb);
 324         }
 325 
 326 
 327         fill(bb, i -> 0);
 328         bb.clear().position(o);
 329         vb.clear();
 330 
 331         for (int i = 0; i < vb.limit(); i++) {
 332             char fromFilled = bbfilled.getChar(o + i * 2);
 333 
 334             bb.putChar(o + i * 2, fromFilled);
 335             char fromBufferView = vb.get(i);
 336             assertValues(i, fromFilled, fromBufferView, bb, vb);
 337         }
 338 
 339         for (int i = 0; i < vb.limit(); i++) {
 340             char fromFilled = bbfilled.getChar(o + i * 2);
 341 
 342             bb.putChar(fromFilled);
 343             char fromBufferView = vb.get();
 344             assertValues(i, fromFilled, fromBufferView, bb, vb);
 345         }
 346     }
 347 
 348     static char getCharFromBytes(ByteBuffer bb, int i) {
 349         return (char) getShortFromBytes(bb, i);
 350     }
 351 
 352 
 353     @DataProvider
 354     public static Object[][] intViewProvider() {
 355         List<Map.Entry<String, Function<ByteBuffer, IntBuffer>>> bfs = List.of(
 356                 Map.entry("bb.asIntBuffer()",
 357                           bb -> bb.asIntBuffer()),
 358                 Map.entry("bb.asIntBuffer().slice()",
 359                           bb -> bb.asIntBuffer().slice()),
 360                 Map.entry("bb.asIntBuffer().slice().duplicate()",
 361                           bb -> bb.asIntBuffer().slice().duplicate())
 362         );
 363 
 364         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 365     }
 366 
 367     @Test(dataProvider = "intViewProvider")
 368     public void testIntGet(String desc, IntFunction<ByteBuffer> fbb,
 369                            Function<ByteBuffer, IntBuffer> fbi) {
 370         ByteBuffer bb = allocate(fbb);
 371         IntBuffer vb = fbi.apply(bb);
 372         int o = bb.position();
 373 
 374         for (int i = 0; i < vb.limit(); i++) {
 375             int fromBytes = getIntFromBytes(bb, o + i * 4);
 376             int fromMethodView = bb.getInt(o + i * 4);
 377             assertValues(i, fromBytes, fromMethodView, bb);
 378 
 379             int fromBufferView = vb.get(i);
 380             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 381         }
 382 
 383         for (int i = 0; i < vb.limit(); i++) {
 384             int v = getIntFromBytes(bb, o + i * 4);
 385             int a = bb.getInt();
 386             assertValues(i, v, a, bb);
 387 
 388             int b = vb.get();
 389             assertValues(i, a, b, bb, vb);
 390         }
 391 
 392     }
 393 
 394     @Test(dataProvider = "intViewProvider")
 395     public void testIntPut(String desc, IntFunction<ByteBuffer> fbb,
 396                            Function<ByteBuffer, IntBuffer> fbi) {
 397         ByteBuffer bbfilled = allocate(fbb);
 398         ByteBuffer bb = allocate(fbb, i -> 0);
 399         IntBuffer vb = fbi.apply(bb);
 400         int o = bb.position();
 401 
 402         for (int i = 0; i < vb.limit(); i++) {
 403             int fromFilled = bbfilled.getInt(o + i * 4);
 404 
 405             vb.put(i, fromFilled);
 406             int fromMethodView = bb.getInt(o + i * 4);
 407             assertValues(i, fromFilled, fromMethodView, bb, vb);
 408         }
 409 
 410         for (int i = 0; i < vb.limit(); i++) {
 411             int fromFilled = bbfilled.getInt(o + i * 4);
 412 
 413             vb.put(fromFilled);
 414             int fromMethodView = bb.getInt();
 415             assertValues(i, fromFilled, fromMethodView, bb, vb);
 416         }
 417 
 418 
 419         fill(bb, i -> 0);
 420         bb.clear().position(o);
 421         vb.clear();
 422 
 423         for (int i = 0; i < vb.limit(); i++) {
 424             int fromFilled = bbfilled.getInt(o + i * 4);
 425 
 426             bb.putInt(o + i * 4, fromFilled);
 427             int fromBufferView = vb.get(i);
 428             assertValues(i, fromFilled, fromBufferView, bb, vb);
 429         }
 430 
 431         for (int i = 0; i < vb.limit(); i++) {
 432             int fromFilled = bbfilled.getInt(o + i * 4);
 433 
 434             bb.putInt(fromFilled);
 435             int fromBufferView = vb.get();
 436             assertValues(i, fromFilled, fromBufferView, bb, vb);
 437         }
 438     }
 439 
 440     static int getIntFromBytes(ByteBuffer bb, int i) {
 441         int a = bb.get(i) & 0xFF;
 442         int b = bb.get(i + 1) & 0xFF;
 443         int c = bb.get(i + 2) & 0xFF;
 444         int d = bb.get(i + 3) & 0xFF;
 445 
 446         if (bb.order() == ByteOrder.BIG_ENDIAN) {
 447             return ((a << 24) | (b << 16) | (c << 8) | d);
 448         }
 449         else {
 450             return ((d << 24) | (c << 16) | (b << 8) | a);
 451         }
 452     }
 453 
 454 
 455     @DataProvider
 456     public static Object[][] longViewProvider() {
 457         List<Map.Entry<String, Function<ByteBuffer, LongBuffer>>> bfs = List.of(
 458                 Map.entry("bb.asLongBuffer()",
 459                           bb -> bb.asLongBuffer()),
 460                 Map.entry("bb.asLongBuffer().slice()",
 461                           bb -> bb.asLongBuffer().slice()),
 462                 Map.entry("bb.asLongBuffer().slice().duplicate()",
 463                           bb -> bb.asLongBuffer().slice().duplicate())
 464         );
 465 
 466         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 467     }
 468 
 469     @Test(dataProvider = "longViewProvider")
 470     public void testLongGet(String desc, IntFunction<ByteBuffer> fbb,
 471                             Function<ByteBuffer, LongBuffer> fbi) {
 472         ByteBuffer bb = allocate(fbb);
 473         LongBuffer vb = fbi.apply(bb);
 474         int o = bb.position();
 475 
 476         for (int i = 0; i < vb.limit(); i++) {
 477             long fromBytes = getLongFromBytes(bb, o + i * 8);
 478             long fromMethodView = bb.getLong(o + i * 8);
 479             assertValues(i, fromBytes, fromMethodView, bb);
 480 
 481             long fromBufferView = vb.get(i);
 482             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 483         }
 484 
 485         for (int i = 0; i < vb.limit(); i++) {
 486             long v = getLongFromBytes(bb, o + i * 8);
 487             long a = bb.getLong();
 488             assertValues(i, v, a, bb);
 489 
 490             long b = vb.get();
 491             assertValues(i, a, b, bb, vb);
 492         }
 493 
 494     }
 495 
 496     @Test(dataProvider = "longViewProvider")
 497     public void testLongPut(String desc, IntFunction<ByteBuffer> fbb,
 498                             Function<ByteBuffer, LongBuffer> fbi) {
 499         ByteBuffer bbfilled = allocate(fbb);
 500         ByteBuffer bb = allocate(fbb, i -> 0);
 501         LongBuffer vb = fbi.apply(bb);
 502         int o = bb.position();
 503 
 504         for (int i = 0; i < vb.limit(); i++) {
 505             long fromFilled = bbfilled.getLong(o + i * 8);
 506 
 507             vb.put(i, fromFilled);
 508             long fromMethodView = bb.getLong(o + i * 8);
 509             assertValues(i, fromFilled, fromMethodView, bb, vb);
 510         }
 511 
 512         for (int i = 0; i < vb.limit(); i++) {
 513             long fromFilled = bbfilled.getLong(o + i * 8);
 514 
 515             vb.put(fromFilled);
 516             long fromMethodView = bb.getLong();
 517             assertValues(i, fromFilled, fromMethodView, bb, vb);
 518         }
 519 
 520 
 521         fill(bb, i -> 0);
 522         bb.clear().position(o);
 523         vb.clear();
 524 
 525         for (int i = 0; i < vb.limit(); i++) {
 526             long fromFilled = bbfilled.getLong(o + i * 8);
 527 
 528             bb.putLong(o + i * 8, fromFilled);
 529             long fromBufferView = vb.get(i);
 530             assertValues(i, fromFilled, fromBufferView, bb, vb);
 531         }
 532 
 533         for (int i = 0; i < vb.limit(); i++) {
 534             long fromFilled = bbfilled.getLong(o + i * 8);
 535 
 536             bb.putLong(fromFilled);
 537             long fromBufferView = vb.get();
 538             assertValues(i, fromFilled, fromBufferView, bb, vb);
 539         }
 540     }
 541 
 542     static long getLongFromBytes(ByteBuffer bb, int i) {
 543         long a = bb.get(i) & 0xFF;
 544         long b = bb.get(i + 1) & 0xFF;
 545         long c = bb.get(i + 2) & 0xFF;
 546         long d = bb.get(i + 3) & 0xFF;
 547         long e = bb.get(i + 4) & 0xFF;
 548         long f = bb.get(i + 5) & 0xFF;
 549         long g = bb.get(i + 6) & 0xFF;
 550         long h = bb.get(i + 7) & 0xFF;
 551 
 552         if (bb.order() == ByteOrder.BIG_ENDIAN) {
 553             return ((a << 56) | (b << 48) | (c << 40) | (d << 32) |
 554                     (e << 24) | (f << 16) | (g << 8) | h);
 555         }
 556         else {
 557             return ((h << 56) | (g << 48) | (f << 40) | (e << 32) |
 558                     (d << 24) | (c << 16) | (b << 8) | a);
 559         }
 560     }
 561 
 562 
 563     @DataProvider
 564     public static Object[][] floatViewProvider() {
 565         List<Map.Entry<String, Function<ByteBuffer, FloatBuffer>>> bfs = List.of(
 566                 Map.entry("bb.asFloatBuffer()",
 567                           bb -> bb.asFloatBuffer()),
 568                 Map.entry("bb.asFloatBuffer().slice()",
 569                           bb -> bb.asFloatBuffer().slice()),
 570                 Map.entry("bb.asFloatBuffer().slice().duplicate()",
 571                           bb -> bb.asFloatBuffer().slice().duplicate())
 572         );
 573 
 574         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 575     }
 576 
 577     @Test(dataProvider = "floatViewProvider")
 578     public void testFloatGet(String desc, IntFunction<ByteBuffer> fbb,
 579                              Function<ByteBuffer, FloatBuffer> fbi) {
 580         ByteBuffer bb = allocate(fbb);
 581         FloatBuffer vb = fbi.apply(bb);
 582         int o = bb.position();
 583 
 584         for (int i = 0; i < vb.limit(); i++) {
 585             float fromBytes = getFloatFromBytes(bb, o + i * 4);
 586             float fromMethodView = bb.getFloat(o + i * 4);
 587             assertValues(i, fromBytes, fromMethodView, bb);
 588 
 589             float fromBufferView = vb.get(i);
 590             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 591         }
 592 
 593         for (int i = 0; i < vb.limit(); i++) {
 594             float v = getFloatFromBytes(bb, o + i * 4);
 595             float a = bb.getFloat();
 596             assertValues(i, v, a, bb);
 597 
 598             float b = vb.get();
 599             assertValues(i, a, b, bb, vb);
 600         }
 601 
 602     }
 603 
 604     @Test(dataProvider = "floatViewProvider")
 605     public void testFloatPut(String desc, IntFunction<ByteBuffer> fbb,
 606                              Function<ByteBuffer, FloatBuffer> fbi) {
 607         ByteBuffer bbfilled = allocate(fbb);
 608         ByteBuffer bb = allocate(fbb, i -> 0);
 609         FloatBuffer vb = fbi.apply(bb);
 610         int o = bb.position();
 611 
 612         for (int i = 0; i < vb.limit(); i++) {
 613             float fromFilled = bbfilled.getFloat(o + i * 4);
 614 
 615             vb.put(i, fromFilled);
 616             float fromMethodView = bb.getFloat(o + i * 4);
 617             assertValues(i, fromFilled, fromMethodView, bb, vb);
 618         }
 619 
 620         for (int i = 0; i < vb.limit(); i++) {
 621             float fromFilled = bbfilled.getFloat(o + i * 4);
 622 
 623             vb.put(fromFilled);
 624             float fromMethodView = bb.getFloat();
 625             assertValues(i, fromFilled, fromMethodView, bb, vb);
 626         }
 627 
 628 
 629         fill(bb, i -> 0);
 630         bb.clear().position(o);
 631         vb.clear();
 632 
 633         for (int i = 0; i < vb.limit(); i++) {
 634             float fromFilled = bbfilled.getFloat(o + i * 4);
 635 
 636             bb.putFloat(o + i * 4, fromFilled);
 637             float fromBufferView = vb.get(i);
 638             assertValues(i, fromFilled, fromBufferView, bb, vb);
 639         }
 640 
 641         for (int i = 0; i < vb.limit(); i++) {
 642             float fromFilled = bbfilled.getFloat(o + i * 4);
 643 
 644             bb.putFloat(fromFilled);
 645             float fromBufferView = vb.get();
 646             assertValues(i, fromFilled, fromBufferView, bb, vb);
 647         }
 648     }
 649 
 650     static float getFloatFromBytes(ByteBuffer bb, int i) {
 651         return Float.intBitsToFloat(getIntFromBytes(bb, i));
 652     }
 653 
 654 
 655 
 656     @DataProvider
 657     public static Object[][] doubleViewProvider() {
 658         List<Map.Entry<String, Function<ByteBuffer, DoubleBuffer>>> bfs = List.of(
 659                 Map.entry("bb.asDoubleBuffer()",
 660                           bb -> bb.asDoubleBuffer()),
 661                 Map.entry("bb.asDoubleBuffer().slice()",
 662                           bb -> bb.asDoubleBuffer().slice()),
 663                 Map.entry("bb.asDoubleBuffer().slice().duplicate()",
 664                           bb -> bb.asDoubleBuffer().slice().duplicate())
 665         );
 666 
 667         return product(BYTE_BUFFER_FUNCTIONS, bfs);
 668     }
 669 
 670     @Test(dataProvider = "doubleViewProvider")
 671     public void testDoubleGet(String desc, IntFunction<ByteBuffer> fbb,
 672                               Function<ByteBuffer, DoubleBuffer> fbi) {
 673         ByteBuffer bb = allocate(fbb);
 674         DoubleBuffer vb = fbi.apply(bb);
 675         int o = bb.position();
 676 
 677         for (int i = 0; i < vb.limit(); i++) {
 678             double fromBytes = getDoubleFromBytes(bb, o + i * 8);
 679             double fromMethodView = bb.getDouble(o + i * 8);
 680             assertValues(i, fromBytes, fromMethodView, bb);
 681 
 682             double fromBufferView = vb.get(i);
 683             assertValues(i, fromMethodView, fromBufferView, bb, vb);
 684         }
 685 
 686         for (int i = 0; i < vb.limit(); i++) {
 687             double v = getDoubleFromBytes(bb, o + i * 8);
 688             double a = bb.getDouble();
 689             assertValues(i, v, a, bb);
 690 
 691             double b = vb.get();
 692             assertValues(i, a, b, bb, vb);
 693         }
 694 
 695     }
 696 
 697     @Test(dataProvider = "doubleViewProvider")
 698     public void testDoublePut(String desc, IntFunction<ByteBuffer> fbb,
 699                               Function<ByteBuffer, DoubleBuffer> fbi) {
 700         ByteBuffer bbfilled = allocate(fbb);
 701         ByteBuffer bb = allocate(fbb, i -> 0);
 702         DoubleBuffer vb = fbi.apply(bb);
 703         int o = bb.position();
 704 
 705         for (int i = 0; i < vb.limit(); i++) {
 706             double fromFilled = bbfilled.getDouble(o + i * 8);
 707 
 708             vb.put(i, fromFilled);
 709             double fromMethodView = bb.getDouble(o + i * 8);
 710             assertValues(i, fromFilled, fromMethodView, bb, vb);
 711         }
 712 
 713         for (int i = 0; i < vb.limit(); i++) {
 714             double fromFilled = bbfilled.getDouble(o + i * 8);
 715 
 716             vb.put(fromFilled);
 717             double fromMethodView = bb.getDouble();
 718             assertValues(i, fromFilled, fromMethodView, bb, vb);
 719         }
 720 
 721 
 722         fill(bb, i -> 0);
 723         bb.clear().position(o);
 724         vb.clear();
 725 
 726         for (int i = 0; i < vb.limit(); i++) {
 727             double fromFilled = bbfilled.getDouble(o + i * 8);
 728 
 729             bb.putDouble(o + i * 8, fromFilled);
 730             double fromBufferView = vb.get(i);
 731             assertValues(i, fromFilled, fromBufferView, bb, vb);
 732         }
 733 
 734         for (int i = 0; i < vb.limit(); i++) {
 735             double fromFilled = bbfilled.getDouble(o + i * 8);
 736 
 737             bb.putDouble(fromFilled);
 738             double fromBufferView = vb.get();
 739             assertValues(i, fromFilled, fromBufferView, bb, vb);
 740         }
 741     }
 742 
 743     static double getDoubleFromBytes(ByteBuffer bb, int i) {
 744         return Double.longBitsToDouble(getLongFromBytes(bb, i));
 745     }
 746 }