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