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
30import org.testng.annotations.DataProvider;
31import org.testng.annotations.Test;
32
33import java.nio.Buffer;
34import java.nio.ByteBuffer;
35import java.nio.ByteOrder;
36import java.nio.CharBuffer;
37import java.nio.DoubleBuffer;
38import java.nio.FloatBuffer;
39import java.nio.IntBuffer;
40import java.nio.LongBuffer;
41import java.nio.ShortBuffer;
42import java.util.List;
43import java.util.Map;
44import java.util.function.Function;
45import java.util.function.IntFunction;
46import java.util.function.IntUnaryOperator;
47import java.util.function.UnaryOperator;
48import java.util.stream.Collectors;
49
50import static org.testng.Assert.*;
51
52public 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}
747