/*
 * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @modules java.base/sun.nio.ch java.base/jdk.internal.foreign
 * @run testng/othervm/timeout=600 --enable-native-access=ALL-UNNAMED TestByteBuffer
 */

import java.lang.foreign.*;
import java.lang.foreign.MemoryLayout.PathElement;

import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.ref.Cleaner;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.MappedByteBuffer;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.testng.SkipException;
import org.testng.annotations.*;
import sun.nio.ch.DirectBuffer;

import static java.lang.foreign.ValueLayout.*;
import static org.testng.Assert.*;

public class TestByteBuffer {

    static final Path tempPath;

    static {
        try {
            File file = File.createTempFile("buffer", "txt");
            file.deleteOnExit();
            tempPath = file.toPath();
            Files.write(file.toPath(), new byte[256], StandardOpenOption.WRITE);

        } catch (IOException ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    static final ValueLayout.OfChar BB_CHAR = JAVA_CHAR_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);
    static final ValueLayout.OfShort BB_SHORT = JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);
    static final ValueLayout.OfInt BB_INT = JAVA_INT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);
    static final ValueLayout.OfLong BB_LONG = JAVA_LONG_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);
    static final ValueLayout.OfFloat BB_FLOAT = JAVA_FLOAT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);
    static final ValueLayout.OfDouble BB_DOUBLE = JAVA_DOUBLE_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN);

    static SequenceLayout tuples = MemoryLayout.sequenceLayout(500,
            MemoryLayout.structLayout(
                    BB_INT.withName("index"),
                    BB_FLOAT.withName("value")
            ));

    static final SequenceLayout bytes = MemoryLayout.sequenceLayout(100, JAVA_BYTE);
    static final SequenceLayout chars = MemoryLayout.sequenceLayout(100, BB_CHAR);
    static final SequenceLayout shorts = MemoryLayout.sequenceLayout(100, BB_SHORT);
    static final SequenceLayout ints = MemoryLayout.sequenceLayout(100, BB_INT);
    static final SequenceLayout floats = MemoryLayout.sequenceLayout(100, BB_FLOAT);
    static final SequenceLayout longs = MemoryLayout.sequenceLayout(100, BB_LONG);
    static final SequenceLayout doubles = MemoryLayout.sequenceLayout(100, BB_DOUBLE);

    static final VarHandle indexHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("index"));
    static final VarHandle valueHandle = tuples.varHandle(PathElement.sequenceElement(), PathElement.groupElement("value"));

    static void initTuples(MemorySegment base, long count) {
        for (long i = 0; i < count ; i++) {
            indexHandle.set(base, 0L, i, (int)i);
            valueHandle.set(base, 0L, i, (float)(i / 500f));
        }
    }

    static void checkTuples(MemorySegment base, ByteBuffer bb, long count) {
        for (long i = 0; i < count ; i++) {
            int index;
            float value;
            assertEquals(index = bb.getInt(), (int)indexHandle.get(base, 0L, i));
            assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, 0L, i));
            assertEquals(value, index / 500f);
        }
    }

    static void initBytes(MemorySegment base, SequenceLayout seq, BiConsumer<MemorySegment, Long> handleSetter) {
        for (long i = 0; i < seq.elementCount() ; i++) {
            handleSetter.accept(base, i);
        }
    }

    static <Z extends Buffer> void checkBytes(MemorySegment base, SequenceLayout layout,
                                              Function<ByteBuffer, Z> bufFactory,
                                              BiFunction<MemorySegment, Long, Object> handleExtractor,
                                              Function<Z, Object> bufferExtractor) {
        long nelems = layout.elementCount();
        long elemSize = layout.elementLayout().byteSize();
        for (long i = 0 ; i < nelems ; i++) {
            long limit = nelems - i;
            MemorySegment resizedSegment = base.asSlice(i * elemSize, limit * elemSize);
            ByteBuffer bb = resizedSegment.asByteBuffer();
            Z z = bufFactory.apply(bb);
            MemorySegment segmentBufferView = MemorySegment.ofBuffer(z);
            for (long j = i ; j < limit ; j++) {
                Object handleValue = handleExtractor.apply(resizedSegment, j - i);
                Object bufferValue = bufferExtractor.apply(z);
                Object handleViewValue = handleExtractor.apply(segmentBufferView, j - i);
                if (handleValue instanceof Number) {
                    assertEquals(((Number)handleValue).longValue(), j);
                    assertEquals(((Number)bufferValue).longValue(), j);
                    assertEquals(((Number)handleViewValue).longValue(), j);
                } else {
                    assertEquals((long)(char)handleValue, j);
                    assertEquals((long)(char)bufferValue, j);
                    assertEquals((long)(char)handleViewValue, j);
                }
            }
        }
    }

    @Test
    public void testOffheap() {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(tuples);
            initTuples(segment, tuples.elementCount());

            ByteBuffer bb = segment.asByteBuffer();
            checkTuples(segment, bb, tuples.elementCount());
        }
    }

    @Test
    public void testHeap() {
        byte[] arr = new byte[(int) tuples.byteSize()];
        MemorySegment region = MemorySegment.ofArray(arr);
        initTuples(region, tuples.elementCount());

        ByteBuffer bb = region.asByteBuffer();
        checkTuples(region, bb, tuples.elementCount());
    }

    @Test
    public void testChannel() throws Throwable {
        File f = new File("test.out");
        assertTrue(f.createNewFile());
        f.deleteOnExit();

        //write to channel
        try (FileChannel channel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            withMappedBuffer(channel, FileChannel.MapMode.READ_WRITE, 0, tuples.byteSize(), mbb -> {
                MemorySegment segment = MemorySegment.ofBuffer(mbb);
                initTuples(segment, tuples.elementCount());
                mbb.force();
            });
        }

        //read from channel
        try (FileChannel channel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) {
            withMappedBuffer(channel, FileChannel.MapMode.READ_ONLY, 0, tuples.byteSize(), mbb -> {
                MemorySegment segment = MemorySegment.ofBuffer(mbb);
                checkTuples(segment, mbb, tuples.elementCount());
            });
        }
    }

    @Test
    public void testDefaultAccessModesMappedSegment() throws Throwable {
        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena);
            assertFalse(segment.isReadOnly());
        }

        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, arena);
            assertTrue(segment.isReadOnly());
        }
    }

    @Test
    public void testMappedSegment() throws Throwable {
        File f = new File("test2.out");
        f.createNewFile();
        f.deleteOnExit();

        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            //write to channel
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), arena);
            initTuples(segment, tuples.elementCount());
            segment.force();
        }

        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) {
            //read from channel
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena);
            checkTuples(segment, segment.asByteBuffer(), tuples.elementCount());
        }
    }

    @Test(dataProvider = "mappedOps", expectedExceptions = IllegalStateException.class)
    public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws Throwable {
        File f = new File("test3.out");
        f.createNewFile();
        f.deleteOnExit();

        Arena arena = Arena.ofConfined();
        try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena);
            assertTrue(segment.isMapped());
            assertTrue(segment.toString().contains("mapped"));
            arena.close();
            mappedBufferOp.apply(segment);
        }
    }

    @Test
    public void testMappedSegmentOffset() throws Throwable {
        File f = new File("test3.out");
        f.createNewFile();
        f.deleteOnExit();

        MemoryLayout tupleLayout = tuples.elementLayout();

        // write one at a time
        for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) {
            try (Arena arena = Arena.ofConfined();
                 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
                //write to channel
                MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), arena);
                initTuples(segment, 1);
                segment.force();
            }
        }

        // check one at a time
        for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) {
            try (Arena arena = Arena.ofConfined();
                 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) {
                //read from channel
                MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena);
                checkTuples(segment, segment.asByteBuffer(), 1);
            }
        }
    }

    @Test(dataProvider = "fromArrays")
    public void testAsByteBufferFromNonByteArray(MemorySegment segment) {
        if (!segment.heapBase().map(a -> a instanceof byte[]).get()) {
            // This should not work as the segment is not backed by a byte array
            assertThrows(UnsupportedOperationException.class, segment::asByteBuffer);
        }
    }

    @Test
    public void testMappedSegmentAsByteBuffer() throws Throwable {
        File f = new File("test4.out");
        assertTrue(f.createNewFile());
        f.deleteOnExit();

        for (var mapOption : List.of(FileChannel.MapMode.READ_WRITE, FileChannel.MapMode.READ_ONLY, FileChannel.MapMode.PRIVATE)) {
            for (var arena : List.of(Arena.ofConfined(), Arena.global())) {
                try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
                    //write to channel
                    MemorySegment segment = fileChannel.map(mapOption, 0L, 32L, arena);
                    segment.force();
                    segment.load();
                    segment.isLoaded();
                    segment.unload();
                    ByteBuffer byteBuffer = segment.asByteBuffer();
                    assertEquals(byteBuffer.capacity(), segment.byteSize());
                    assertEquals(byteBuffer.isReadOnly(), segment.isReadOnly());
                    assertTrue(byteBuffer.isDirect());
                } catch (IOException e) {
                    if (e.getMessage().equals("Function not implemented"))
                        throw new SkipException(e.getMessage(), e);
                } finally {
                    if (arena.scope() != Arena.global().scope()) {
                        arena.close();
                    }
                }
            }
        }
    }

    static final long LARGE_SIZE = (2L * 1024L + 512L) * 1024L * 1024L; // 2.5 GiB

    @Test
    public void testLargeMappedSegment() throws Throwable {
        if (System.getProperty("sun.arch.data.model").equals("32")) {
            throw new SkipException("large mapped files not supported on 32-bit systems");
        }

        File f = new File("testLargeMappedSegment.out");
        f.createNewFile();
        f.deleteOnExit();

        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, arena);
            segment.isLoaded();
            segment.load();
            segment.isLoaded();
            segment.force();
            segment.isLoaded();
            segment.unload();
            segment.isLoaded();
        } catch(IOException e) {
            if (e.getMessage().equals("Function not implemented"))
                throw new SkipException(e.getMessage(), e);
        }
    }

    static void withMappedBuffer(FileChannel channel, FileChannel.MapMode mode, long pos, long size, Consumer<MappedByteBuffer> action) throws Throwable {
        MappedByteBuffer mbb = channel.map(mode, pos, size);
        var ref = new WeakReference<>(mbb);
        action.accept(mbb);
        mbb = null;
        //wait for it to be GCed
        System.gc();
        while (ref.get() != null) {
            Thread.sleep(20);
        }
    }

    static void checkByteArrayAlignment(MemoryLayout layout) {
        if (layout.byteSize() > 4
                && System.getProperty("sun.arch.data.model").equals("32")) {
            throw new SkipException("avoid unaligned access on 32-bit system");
        }
    }

    @Test(dataProvider = "bufferOps")
    public void testScopedBuffer(Function<ByteBuffer, Buffer> bufferFactory, @NoInjection Method method, Object[] args) {
        Buffer bb;
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(bytes);
            bb = bufferFactory.apply(segment.asByteBuffer());
        }
        //outside of session!!
        try {
            method.invoke(bb, args);
            fail("Exception expected");
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();
            if (cause instanceof IllegalStateException) {
                //all get/set buffer operation should fail because of the session check
                assertTrue(ex.getCause().getMessage().contains("Already closed"));
            } else {
                //all other exceptions were unexpected - fail
                fail("Unexpected exception", cause);
            }
        } catch (Throwable ex) {
            //unexpected exception - fail
            fail("Unexpected exception", ex);
        }
    }

    @Test(dataProvider = "bufferHandleOps")
    public void testScopedBufferAndVarHandle(VarHandle bufferHandle) {
        ByteBuffer bb;
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(bytes, Long.BYTES);
            bb = segment.asByteBuffer();
            for (Map.Entry<MethodHandle, Object[]> e : varHandleMembers(bb, bufferHandle).entrySet()) {
                MethodHandle handle = e.getKey().bindTo(bufferHandle)
                        .asSpreader(Object[].class, e.getValue().length);
                try {
                    handle.invoke(e.getValue());
                } catch (UnsupportedOperationException ex) {
                    //skip
                } catch (Throwable ex) {
                    //should not fail - segment is alive!
                    fail();
                }
            }
        }
        for (Map.Entry<MethodHandle, Object[]> e : varHandleMembers(bb, bufferHandle).entrySet()) {
            try {
                MethodHandle handle = e.getKey().bindTo(bufferHandle)
                        .asSpreader(Object[].class, e.getValue().length);
                handle.invoke(e.getValue());
                fail();
            } catch (IllegalStateException ex) {
                assertTrue(ex.getMessage().contains("Already closed"));
            } catch (UnsupportedOperationException ex) {
                //skip
            } catch (Throwable ex) {
                fail();
            }
        }
    }

    @Test(dataProvider = "bufferOps")
    public void testDirectBuffer(Function<ByteBuffer, Buffer> bufferFactory, @NoInjection Method method, Object[] args) {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(bytes);
            Buffer bb = bufferFactory.apply(segment.asByteBuffer());
            assertTrue(bb.isDirect());
            DirectBuffer directBuffer = ((DirectBuffer)bb);
            assertEquals(directBuffer.address(), segment.address());
            assertTrue((directBuffer.attachment() == null) == (bb instanceof ByteBuffer));
            assertTrue(directBuffer.cleaner() == null);
        }
    }

    @Test(dataProvider="resizeOps")
    public void testResizeOffheap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(seq);
            initializer.accept(segment);
            checker.accept(segment);
        }
    }

    @Test(dataProvider="resizeOps")
    public void testResizeHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        checkByteArrayAlignment(seq.elementLayout());
        int capacity = (int)seq.byteSize();
        MemorySegment base = MemorySegment.ofArray(new byte[capacity]);
        initializer.accept(base);
        checker.accept(base);
    }

    @Test(dataProvider="resizeOps")
    public void testResizeBuffer(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        checkByteArrayAlignment(seq.elementLayout());
        int capacity = (int)seq.byteSize();
        MemorySegment base = MemorySegment.ofBuffer(ByteBuffer.wrap(new byte[capacity]));
        initializer.accept(base);
        checker.accept(base);
    }

    @Test(dataProvider="resizeOps")
    public void testResizeRoundtripHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        checkByteArrayAlignment(seq.elementLayout());
        int capacity = (int)seq.byteSize();
        byte[] arr = new byte[capacity];
        MemorySegment segment = MemorySegment.ofArray(arr);
        initializer.accept(segment);
        MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer());
        checker.accept(second);
    }

    @Test(dataProvider="resizeOps")
    public void testResizeRoundtripNative(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment segment = arena.allocate(seq);
            initializer.accept(segment);
            MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer());
            checker.accept(second);
        }
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void testBufferOnClosedSession() {
        MemorySegment leaked;
        try (Arena arena = Arena.ofConfined()) {
            leaked = arena.allocate(bytes);
        }
        ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok
        byteBuffer.get(); // should throw
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void testTooBigForByteBuffer() {
        MemorySegment segment = MemorySegment.NULL.reinterpret(Integer.MAX_VALUE + 10L);
        segment.asByteBuffer();
    }

    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testBadMapNegativeSize() throws IOException {
        File f = new File("testNeg1.out");
        f.createNewFile();
        f.deleteOnExit();
        try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, Arena.ofAuto());
        }
    }

    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testBadMapNegativeOffset() throws IOException {
        File f = new File("testNeg2.out");
        f.createNewFile();
        f.deleteOnExit();
        try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, Arena.ofAuto());
        }
    }

    @Test
    public void testMapOffset() throws IOException {
        File f = new File("testMapOffset.out");
        f.createNewFile();
        f.deleteOnExit();

        int SIZE = Byte.MAX_VALUE;

        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, arena);
            for (byte offset = 0; offset < SIZE; offset++) {
                segment.set(JAVA_BYTE, offset, offset);
            }
            segment.force();
        }

        for (int offset = 0 ; offset < SIZE ; offset++) {
            try (Arena arena = Arena.ofConfined();
                 FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) {
                MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, arena);
                assertEquals(segment.get(JAVA_BYTE, 0), offset);
            }
        }
    }

    @Test
    public void testMapZeroSize() throws IOException {
        File f = new File("testPos1.out");
        f.createNewFile();
        f.deleteOnExit();
        //RW
        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, arena);
            assertEquals(segment.byteSize(), 0);
            assertEquals(segment.isMapped(), true);
            assertFalse(segment.isReadOnly());
            segment.force();
            segment.load();
            segment.isLoaded();
            segment.unload();
            ByteBuffer byteBuffer = segment.asByteBuffer();
            assertEquals(byteBuffer.capacity(), 0);
            assertFalse(byteBuffer.isReadOnly());
        }
        //RO
        try (Arena arena = Arena.ofConfined();
             FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) {
            MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, arena);
            assertEquals(segment.byteSize(), 0);
            assertEquals(segment.isMapped(), true);
            assertTrue(segment.isReadOnly());
            segment.force();
            segment.load();
            segment.isLoaded();
            segment.unload();
            ByteBuffer byteBuffer = segment.asByteBuffer();
            assertEquals(byteBuffer.capacity(), 0);
            assertTrue(byteBuffer.isReadOnly());
        }
    }

    @Test(expectedExceptions = UnsupportedOperationException.class)
    public void testMapCustomPath() throws IOException {
        Path path = Path.of(URI.create("jrt:/"));
        try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, Arena.ofAuto());
        }
    }

    @Test(dataProvider="resizeOps")
    public void testCopyHeapToNative(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        checkByteArrayAlignment(seq.elementLayout());
        int bytes = (int)seq.byteSize();
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment nativeArray = arena.allocate(bytes, 1);
            MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]);
            initializer.accept(heapArray);
            nativeArray.copyFrom(heapArray);
            checker.accept(nativeArray);
        }
    }

    @Test(dataProvider="resizeOps")
    public void testCopyNativeToHeap(Consumer<MemorySegment> checker, Consumer<MemorySegment> initializer, SequenceLayout seq) {
        checkByteArrayAlignment(seq.elementLayout());
        int bytes = (int)seq.byteSize();
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment nativeArray = arena.allocate(seq);
            MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]);
            initializer.accept(nativeArray);
            heapArray.copyFrom(nativeArray);
            checker.accept(heapArray);
        }
    }

    @Test
    public void testDefaultAccessModesOfBuffer() {
        ByteBuffer rwBuffer = ByteBuffer.wrap(new byte[4]);
        {
            MemorySegment segment = MemorySegment.ofBuffer(rwBuffer);
            assertFalse(segment.isReadOnly());
        }

        {
            ByteBuffer roBuffer = rwBuffer.asReadOnlyBuffer();
            MemorySegment segment = MemorySegment.ofBuffer(roBuffer);
            assertTrue(segment.isReadOnly());
        }
    }

    @Test
    public void testOfBufferScopeReachable() throws InterruptedException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(1000);
        MemorySegment segment = MemorySegment.ofBuffer(buffer);
        try {
            AtomicBoolean reachable = new AtomicBoolean(true);
            Cleaner.create().register(buffer, () -> {
                reachable.set(false);
            });
            buffer = null;
            System.gc();
            // let's sleep to let cleaner run
            Thread.sleep(100);
            segment.get(JAVA_BYTE, 0);
            if (!reachable.get()) {
                throw new IllegalStateException();
            }
        } finally {
            Reference.reachabilityFence(segment);
        }
    }

    @Test(dataProvider="bufferSources")
    public void testBufferToSegment(ByteBuffer bb, Predicate<MemorySegment> segmentChecker) {
        MemorySegment segment = MemorySegment.ofBuffer(bb);
        assertEquals(segment.isReadOnly(), bb.isReadOnly());
        assertTrue(segmentChecker.test(segment));
        assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize())));
        assertEquals(bb.capacity(), segment.byteSize());
        //another round trip
        segment = MemorySegment.ofBuffer(segment.asByteBuffer());
        assertEquals(segment.isReadOnly(), bb.isReadOnly());
        assertTrue(segmentChecker.test(segment));
        assertTrue(segmentChecker.test(segment.asSlice(0, segment.byteSize())));
        assertEquals(bb.capacity(), segment.byteSize());
    }

    @Test(dataProvider="bufferSources")
    public void bufferProperties(ByteBuffer bb, Predicate<MemorySegment> _unused) {
        MemorySegment segment = MemorySegment.ofBuffer(bb);
        ByteBuffer buffer = segment.asByteBuffer();
        assertEquals(buffer.position(), 0);
        assertEquals(buffer.capacity(), segment.byteSize());
        assertEquals(buffer.limit(), segment.byteSize());
    }

    @Test
    public void testRoundTripAccess() {
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment ms = arena.allocate(4, 1);
            MemorySegment msNoAccess = ms.asReadOnly();
            MemorySegment msRoundTrip = MemorySegment.ofBuffer(msNoAccess.asByteBuffer());
            assertEquals(msRoundTrip.scope(), ms.scope());
            assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly());
        }
    }

    @Test(dataProvider = "bufferFactories")
    public void testDerivedBufferScopes(Supplier<Buffer> bufferFactory) {
        MemorySegment segment = MemorySegment.ofBuffer(bufferFactory.get());
        assertEquals(segment.scope(), segment.scope());
        // one level
        assertEquals(segment.asSlice(0).scope(), segment.scope());
        assertEquals(segment.asReadOnly().scope(), segment.scope());
        // two levels
        assertEquals(segment.asSlice(0).asReadOnly().scope(), segment.scope());
        assertEquals(segment.asReadOnly().asSlice(0).scope(), segment.scope());
        // check fresh every time
        MemorySegment another = MemorySegment.ofBuffer(bufferFactory.get());
        assertNotEquals(segment.scope(), another.scope());
    }

    @Test(expectedExceptions = IllegalStateException.class)
    public void testDeadAccessOnClosedBufferSegment() {
        Arena arena = Arena.ofConfined();
        MemorySegment s1 = arena.allocate(JAVA_INT);
        MemorySegment s2 = MemorySegment.ofBuffer(s1.asByteBuffer());

        // memory freed
        arena.close();

        s2.set(JAVA_INT, 0, 10); // Dead access!
    }

    @Test(dataProvider = "closeableArenas")
    public void closeableArenas(Supplier<Arena> arenaSupplier) throws IOException {
        File tmp = File.createTempFile("tmp", "txt");
        tmp.deleteOnExit();
        try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ;
            Arena arena = arenaSupplier.get()) {
            MemorySegment segment = arena.allocate(10, 1);
            for (int i = 0; i < 10; i++) {
                segment.set(JAVA_BYTE, i, (byte) i);
            }
            ByteBuffer bb = segment.asByteBuffer();
            assertEquals(channel.write(bb), 10);
            segment.fill((byte)0x00);
            assertEquals(bb.clear(), ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
            assertEquals(channel.position(0).read(bb.clear()), 10);
            assertEquals(bb.flip(), ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
        }
    }

    static final Class<IllegalStateException> ISE = IllegalStateException.class;

    @Test(dataProvider = "closeableArenas")
    public void testIOOnClosedSegmentBuffer(Supplier<Arena> arenaSupplier) throws IOException {
        File tmp = File.createTempFile("tmp", "txt");
        tmp.deleteOnExit();
        Arena arena = arenaSupplier.get();
        try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            MemorySegment segment = arena.allocate(10, 1);
            for (int i = 0; i < 10; i++) {
                segment.set(JAVA_BYTE, i, (byte) i);
            }
            ByteBuffer bb = segment.asByteBuffer();
            arena.close();
            assertThrows(ISE, () -> channel.read(bb));
            assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}));
            assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1));
            assertThrows(ISE, () -> channel.write(bb));
            assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}));
            assertThrows(ISE, () -> channel.write(new ByteBuffer[] {bb}, 0 ,1));
        }
    }

    @Test
    public void buffersAndArraysFromSlices() {
        try (Arena arena = Arena.ofShared()) {
            MemorySegment segment = arena.allocate(16, 1);
            int newSize = 8;
            var slice = segment.asSlice(4, newSize);

            var bytes = slice.toArray(JAVA_BYTE);
            assertEquals(newSize, bytes.length);

            var buffer = slice.asByteBuffer();
            // Fails for heap segments, but passes for native segments:
            assertEquals(0, buffer.position());
            assertEquals(newSize, buffer.limit());
            assertEquals(newSize, buffer.capacity());
        }
    }

    @Test
    public void viewsFromSharedSegment() {
        try (Arena arena = Arena.ofShared()) {
            MemorySegment segment = arena.allocate(16, 1);
            var byteBuffer = segment.asByteBuffer();
            byteBuffer.asReadOnlyBuffer();
            byteBuffer.slice(0, 8);
        }
    }

    @DataProvider(name = "segments")
    public static Object[][] segments() throws Throwable {
        return new Object[][] {
                { (Supplier<MemorySegment>) () -> Arena.ofAuto().allocate(16, 1)},
                { (Supplier<MemorySegment>) () -> Arena.ofConfined().allocate(16, 1)},
                { (Supplier<MemorySegment>) () -> MemorySegment.ofArray(new byte[16]) }
        };
    }

    @DataProvider(name = "closeableArenas")
    public static Object[][] closeableArenas() {
        return new Object[][] {
                { (Supplier<Arena>) Arena::ofConfined},
                { (Supplier<Arena>) Arena::ofShared},
        };
    }

    @DataProvider(name = "bufferOps")
    public static Object[][] bufferOps() throws Throwable {
        List<Object[]> args = new ArrayList<>();
        bufferOpsArgs(args, bb -> bb, ByteBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asCharBuffer, CharBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asShortBuffer, ShortBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asIntBuffer, IntBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asFloatBuffer, FloatBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asLongBuffer, LongBuffer.class);
        bufferOpsArgs(args, ByteBuffer::asDoubleBuffer, DoubleBuffer.class);
        return args.toArray(Object[][]::new);
    }

    static void bufferOpsArgs(List<Object[]> argsList, Function<ByteBuffer, Buffer> factory, Class<?> bufferClass) {
        for (Method m : bufferClass.getMethods()) {
            //skip statics and method declared in j.l.Object
            if (m.getDeclaringClass().equals(Object.class)
                || ((m.getModifiers() & Modifier.STATIC) != 0)
                || (!m.getName().contains("get") && !m.getName().contains("put"))
                || m.getParameterCount() > 2) continue;
            Object[] args = Stream.of(m.getParameterTypes())
                    .map(TestByteBuffer::defaultValue)
                    .toArray();
            argsList.add(new Object[] { factory, m, args });
        }
    }

    @DataProvider(name = "bufferHandleOps")
    public static Object[][] bufferHandleOps() throws Throwable {
        return new Object[][]{
                { MethodHandles.byteBufferViewVarHandle(char[].class, ByteOrder.nativeOrder()) },
                { MethodHandles.byteBufferViewVarHandle(short[].class, ByteOrder.nativeOrder()) },
                { MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.nativeOrder()) },
                { MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.nativeOrder()) },
                { MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.nativeOrder()) },
                { MethodHandles.byteBufferViewVarHandle(double[].class, ByteOrder.nativeOrder()) }
        };
    }

    static Map<MethodHandle, Object[]> varHandleMembers(ByteBuffer bb, VarHandle handle) {
        Map<MethodHandle, Object[]> members = new HashMap<>();
        for (VarHandle.AccessMode mode : VarHandle.AccessMode.values()) {
            Class<?>[] params = handle.accessModeType(mode).parameterArray();
            Object[] args = Stream.concat(Stream.of(bb), Stream.of(params).skip(1)
                    .map(TestByteBuffer::defaultValue))
                    .toArray();
            try {
                members.put(MethodHandles.varHandleInvoker(mode, handle.accessModeType(mode)), args);
            } catch (Throwable ex) {
                throw new AssertionError(ex);
            }
        }
        return members;
    }

    @DataProvider(name = "resizeOps")
    public Object[][] resizeOps() {
        Consumer<MemorySegment> byteInitializer =
                (base) -> initBytes(base, bytes, (addr, pos) -> addr.set(JAVA_BYTE, pos, (byte)(long)pos));
        Consumer<MemorySegment> charInitializer =
                (base) -> initBytes(base, chars, (addr, pos) -> addr.setAtIndex(BB_CHAR, pos, (char)(long)pos));
        Consumer<MemorySegment> shortInitializer =
                (base) -> initBytes(base, shorts, (addr, pos) -> addr.setAtIndex(BB_SHORT, pos, (short)(long)pos));
        Consumer<MemorySegment> intInitializer =
                (base) -> initBytes(base, ints, (addr, pos) -> addr.setAtIndex(BB_INT, pos, (int)(long)pos));
        Consumer<MemorySegment> floatInitializer =
                (base) -> initBytes(base, floats, (addr, pos) -> addr.setAtIndex(BB_FLOAT, pos, (float)(long)pos));
        Consumer<MemorySegment> longInitializer =
                (base) -> initBytes(base, longs, (addr, pos) -> addr.setAtIndex(BB_LONG, pos, (long)pos));
        Consumer<MemorySegment> doubleInitializer =
                (base) -> initBytes(base, doubles, (addr, pos) -> addr.setAtIndex(BB_DOUBLE, pos, (double)(long)pos));

        Consumer<MemorySegment> byteChecker =
                (base) -> checkBytes(base, bytes, Function.identity(), (addr, pos) -> addr.get(JAVA_BYTE, pos), ByteBuffer::get);
        Consumer<MemorySegment> charChecker =
                (base) -> checkBytes(base, chars, ByteBuffer::asCharBuffer, (addr, pos) -> addr.getAtIndex(BB_CHAR, pos), CharBuffer::get);
        Consumer<MemorySegment> shortChecker =
                (base) -> checkBytes(base, shorts, ByteBuffer::asShortBuffer, (addr, pos) -> addr.getAtIndex(BB_SHORT, pos), ShortBuffer::get);
        Consumer<MemorySegment> intChecker =
                (base) -> checkBytes(base, ints, ByteBuffer::asIntBuffer, (addr, pos) -> addr.getAtIndex(BB_INT, pos), IntBuffer::get);
        Consumer<MemorySegment> floatChecker =
                (base) -> checkBytes(base, floats, ByteBuffer::asFloatBuffer, (addr, pos) -> addr.getAtIndex(BB_FLOAT, pos), FloatBuffer::get);
        Consumer<MemorySegment> longChecker =
                (base) -> checkBytes(base, longs, ByteBuffer::asLongBuffer, (addr, pos) -> addr.getAtIndex(BB_LONG, pos), LongBuffer::get);
        Consumer<MemorySegment> doubleChecker =
                (base) -> checkBytes(base, doubles, ByteBuffer::asDoubleBuffer, (addr, pos) -> addr.getAtIndex(BB_DOUBLE, pos), DoubleBuffer::get);

        return new Object[][]{
                {byteChecker, byteInitializer, bytes},
                {charChecker, charInitializer, chars},
                {shortChecker, shortInitializer, shorts},
                {intChecker, intInitializer, ints},
                {floatChecker, floatInitializer, floats},
                {longChecker, longInitializer, longs},
                {doubleChecker, doubleInitializer, doubles}
        };
    }

    static Object defaultValue(Class<?> c) {
        if (c.isPrimitive()) {
            if (c == char.class) {
                return (char)0;
            } else if (c == boolean.class) {
                return false;
            } else if (c == byte.class) {
                return (byte)0;
            } else if (c == short.class) {
                return (short)0;
            } else if (c == int.class) {
                return 0;
            } else if (c == long.class) {
                return 0L;
            } else if (c == float.class) {
                return 0f;
            } else if (c == double.class) {
                return 0d;
            } else {
                throw new IllegalStateException();
            }
        } else if (c.isArray()) {
            if (c == char[].class) {
                return new char[1];
            } else if (c == boolean[].class) {
                return new boolean[1];
            } else if (c == byte[].class) {
                return new byte[1];
            } else if (c == short[].class) {
                return new short[1];
            } else if (c == int[].class) {
                return new int[1];
            } else if (c == long[].class) {
                return new long[1];
            } else if (c == float[].class) {
                return new float[1];
            } else if (c == double[].class) {
                return new double[1];
            } else {
                throw new IllegalStateException();
            }
        } else if (c == String.class) {
            return "asdf";
        } else if (c == ByteBuffer.class) {
            return ByteBuffer.wrap(new byte[1]);
        } else if (c == CharBuffer.class) {
            return CharBuffer.wrap(new char[1]);
        } else if (c == ShortBuffer.class) {
            return ShortBuffer.wrap(new short[1]);
        } else if (c == IntBuffer.class) {
            return IntBuffer.wrap(new int[1]);
        } else if (c == FloatBuffer.class) {
            return FloatBuffer.wrap(new float[1]);
        } else if (c == LongBuffer.class) {
            return LongBuffer.wrap(new long[1]);
        } else if (c == DoubleBuffer.class) {
            return DoubleBuffer.wrap(new double[1]);
        } else {
            return null;
        }
    }

    @DataProvider(name = "bufferSources")
    public static Object[][] bufferSources() {
        Predicate<MemorySegment> heapTest = segment -> !segment.isNative() && !segment.isMapped();
        Predicate<MemorySegment> nativeTest = segment -> segment.isNative() && !segment.isMapped();
        Predicate<MemorySegment> mappedTest = segment -> segment.isNative() && segment.isMapped();
        try (FileChannel channel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
            return new Object[][]{
                    { ByteBuffer.wrap(new byte[256]), heapTest },
                    { ByteBuffer.allocate(256), heapTest },
                    { ByteBuffer.allocateDirect(256), nativeTest },
                    { channel.map(FileChannel.MapMode.READ_WRITE, 0L, 256), mappedTest },

                    { ByteBuffer.wrap(new byte[256]).asReadOnlyBuffer(), heapTest },
                    { ByteBuffer.allocate(256).asReadOnlyBuffer(), heapTest },
                    { ByteBuffer.allocateDirect(256).asReadOnlyBuffer(), nativeTest },
                    { channel.map(FileChannel.MapMode.READ_WRITE, 0L, 256).asReadOnlyBuffer(),
                            mappedTest }
            };
        } catch (IOException ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    enum MappedSegmentOp {
        LOAD(MemorySegment::load),
        UNLOAD(MemorySegment::unload),
        IS_LOADED(MemorySegment::isLoaded),
        FORCE(MemorySegment::force),
        BUFFER_LOAD(m -> ((MappedByteBuffer)m.asByteBuffer()).load()),
        BUFFER_IS_LOADED(m -> ((MappedByteBuffer)m.asByteBuffer()).isLoaded()),
        BUFFER_FORCE(m -> ((MappedByteBuffer)m.asByteBuffer()).force());


        private final Consumer<MemorySegment> segmentOp;

        MappedSegmentOp(Consumer<MemorySegment> segmentOp) {
            this.segmentOp = segmentOp;
        }

        void apply(MemorySegment segment) {
            segmentOp.accept(segment);
        }
    }

    @DataProvider(name = "mappedOps")
    public static Object[][] mappedOps() {
        return Stream.of(MappedSegmentOp.values())
                .map(op -> new Object[] { op })
                .toArray(Object[][]::new);
    }

    @DataProvider(name = "bufferFactories")
    public static Object[][] bufferFactories() {
        List<Supplier<Buffer>> l = List.of(
                () -> ByteBuffer.allocate(10),
                () -> CharBuffer.allocate(10),
                () -> ShortBuffer.allocate(10),
                () -> IntBuffer.allocate(10),
                () -> FloatBuffer.allocate(10),
                () -> LongBuffer.allocate(10),
                () -> DoubleBuffer.allocate(10),
                () -> ByteBuffer.allocateDirect(10),
                () -> ByteBuffer.allocateDirect(10).asCharBuffer(),
                () -> ByteBuffer.allocateDirect(10).asShortBuffer(),
                () -> ByteBuffer.allocateDirect(10).asIntBuffer(),
                () -> ByteBuffer.allocateDirect(10).asFloatBuffer(),
                () -> ByteBuffer.allocateDirect(10).asLongBuffer(),
                () -> ByteBuffer.allocateDirect(10).asDoubleBuffer()
        );
        return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new);

    }
    @DataProvider(name = "fromArrays")
    public static Object[][] fromArrays() {
        int len = 16;
        return Stream.of(
                        MemorySegment.ofArray(new byte[len]),
                        MemorySegment.ofArray(new short[len]),
                        MemorySegment.ofArray(new char[len]),
                        MemorySegment.ofArray(new int[len]),
                        MemorySegment.ofArray(new long[len]),
                        MemorySegment.ofArray(new float[len]),
                        MemorySegment.ofArray(new double[len])
                )
                .map(s -> new Object[] { s })
                .toArray(Object[][]::new);
    }
}
