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
composeBufferFunctions( List<Map.Entry<String, IntFunction<ByteBuffer>>> af, List<Map.Entry<String, UnaryOperator<ByteBuffer>>> of)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
product(List<? extends Map.Entry<String, ?>> la, List<? extends Map.Entry<String, ?>> lb)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 
assertValues(int i, Object bValue, Object bbValue, ByteBuffer bb)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 
assertValues(int i, Object bbValue, Object bvValue, ByteBuffer bb, Buffer bv)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 
allocate(IntFunction<ByteBuffer> f)146     static ByteBuffer allocate(IntFunction<ByteBuffer> f) {
147         return allocate(f, i -> i);
148     }
149 
allocate(IntFunction<ByteBuffer> f, IntUnaryOperator o)150     static ByteBuffer allocate(IntFunction<ByteBuffer> f, IntUnaryOperator o) {
151         return fill(f.apply(SIZE), o);
152     }
153 
fill(ByteBuffer bb, IntUnaryOperator o)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
shortViewProvider()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")
testShortGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, ShortBuffer> fbi)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")
testShortPut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, ShortBuffer> fbi)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 
getShortFromBytes(ByteBuffer bb, int i)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
charViewProvider()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")
testCharGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, CharBuffer> fbi)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")
testCharPut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, CharBuffer> fbi)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 
getCharFromBytes(ByteBuffer bb, int i)348     static char getCharFromBytes(ByteBuffer bb, int i) {
349         return (char) getShortFromBytes(bb, i);
350     }
351 
352 
353     @DataProvider
intViewProvider()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")
testIntGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, IntBuffer> fbi)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")
testIntPut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, IntBuffer> fbi)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 
getIntFromBytes(ByteBuffer bb, int i)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
longViewProvider()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")
testLongGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, LongBuffer> fbi)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")
testLongPut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, LongBuffer> fbi)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 
getLongFromBytes(ByteBuffer bb, int i)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
floatViewProvider()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")
testFloatGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, FloatBuffer> fbi)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")
testFloatPut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, FloatBuffer> fbi)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 
getFloatFromBytes(ByteBuffer bb, int i)650     static float getFloatFromBytes(ByteBuffer bb, int i) {
651         return Float.intBitsToFloat(getIntFromBytes(bb, i));
652     }
653 
654 
655 
656     @DataProvider
doubleViewProvider()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")
testDoubleGet(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, DoubleBuffer> fbi)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")
testDoublePut(String desc, IntFunction<ByteBuffer> fbb, Function<ByteBuffer, DoubleBuffer> fbi)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 
getDoubleFromBytes(ByteBuffer bb, int i)743     static double getDoubleFromBytes(ByteBuffer bb, int i) {
744         return Double.longBitsToDouble(getLongFromBytes(bb, i));
745     }
746 }
747