/*
 * Copyright (c) 2008, 2022, 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
 * @bug 4607272 5041655 6822643 6830721 6842687
 * @summary Unit test for AsynchronousFileChannel
 * @key randomness
 */

import java.io.File;
import java.io.IOException;
import java.lang.foreign.Arena;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.CompletionHandler;
import java.nio.channels.FileLock;
import java.nio.channels.NonWritableChannelException;
import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static java.nio.file.StandardOpenOption.*;

public class Basic {

    // Must be indeterministic
    private static final Random rand = new Random();

    public static void main(String[] args) throws IOException {
        // create temporary file
        File blah = File.createTempFile("blah", null);
        blah.deleteOnExit();

        AsynchronousFileChannel ch = AsynchronousFileChannel
            .open(blah.toPath(), READ, WRITE);
        try {
            // run tests
            testUsingCompletionHandlers(ch);
            testUsingWaitOnResult(ch);
            testInterruptHandlerThread(ch);
        } finally {
            ch.close();
        }

        // run test that expects channel to be closed
        testClosedChannel(ch);

        // these tests open the file themselves
        testLocking(blah.toPath());
        testCustomThreadPool(blah.toPath());
        testAsynchronousClose(blah.toPath());
        testCancel(blah.toPath());
        testTruncate(blah.toPath());

        // eagerly clean-up
        blah.delete();
    }

    /*
     * Generate buffer with random contents
     * Writes buffer to file using a CompletionHandler to consume the result
     *    of each write operation
     * Reads file to EOF to a new buffer using a CompletionHandler to consume
     *    the result of each read operation
     * Compares buffer contents
     */
    static void testUsingCompletionHandlers(AsynchronousFileChannel ch)
        throws IOException
    {
        System.out.println("testUsingCompletionHandlers");

        ch.truncate(0L);

        // generate buffer with random elements and write it to file
        ByteBuffer src = genBuffer();
        writeFully(ch, src, 0L);

        // read to EOF or buffer is full
        ByteBuffer dst = (rand.nextBoolean()) ?
            ByteBuffer.allocateDirect(src.capacity()) :
            ByteBuffer.allocate(src.capacity());
        readAll(ch, dst, 0L);

        // check buffers are the same
        src.flip();
        dst.flip();
        if (!src.equals(dst)) {
            throw new RuntimeException("Contents differ");
        }
    }

    /*
     * Generate buffer with random contents
     * Writes buffer to file, invoking the Future's get method to wait for
     *    each write operation to complete
     * Reads file to EOF to a new buffer, invoking the Future's get method to
     *    wait for each write operation to complete
     * Compares buffer contents
     */
    static void testUsingWaitOnResult(AsynchronousFileChannel ch)
        throws IOException
    {
        System.out.println("testUsingWaitOnResult");

        ch.truncate(0L);

        // generate buffer
        ByteBuffer src = genBuffer();

        // write buffer completely to file
        long position = 0L;
        while (src.hasRemaining()) {
            Future<Integer> result = ch.write(src, position);
            try {
                int n = result.get();
                // update position
                position += n;
            } catch (ExecutionException x) {
                throw new RuntimeException(x.getCause());
            } catch (InterruptedException x) {
                throw new RuntimeException(x);
            }
        }

        // read file into new buffer
        ByteBuffer dst = (rand.nextBoolean()) ?
            ByteBuffer.allocateDirect(src.capacity()) :
            ByteBuffer.allocate(src.capacity());
        position = 0L;
        int n;
        do {
            Future<Integer> result = ch.read(dst, position);
            try {
                n = result.get();

                // update position
                if (n > 0) position += n;
            } catch (ExecutionException x) {
                throw new RuntimeException(x.getCause());
            } catch (InterruptedException x) {
                throw new RuntimeException(x);
            }
        } while (n > 0);

        // check buffers are the same
        src.flip();
        dst.flip();
        if (!src.equals(dst)) {
            throw new RuntimeException("Contents differ");
        }
    }

    // exercise lock methods
    static void testLocking(Path file) throws IOException {
        System.out.println("testLocking");

        AsynchronousFileChannel ch = AsynchronousFileChannel
            .open(file, READ, WRITE);
        FileLock fl;
        try {
            // test 1 - acquire lock and check that tryLock throws
            // OverlappingFileLockException
            try {
                long pos = rand.nextInt(Integer.MAX_VALUE);
                fl = ch.lock(pos, 0, false).get();
                long expectedSize = Long.MAX_VALUE - pos;
                if(fl.size() != expectedSize)
                    throw new RuntimeException("Lock size " + fl.size() +
                        " != " + expectedSize + " for position " + pos);
            } catch (ExecutionException x) {
                throw new RuntimeException(x);
            } catch (InterruptedException x) {
                throw new RuntimeException("Should not be interrupted");
            }
            if (!fl.acquiredBy().equals(ch))
                throw new RuntimeException("FileLock#acquiredBy returned incorrect channel");
            try {
                ch.tryLock();
                throw new RuntimeException("OverlappingFileLockException expected");
            } catch (OverlappingFileLockException x) {
            }
            fl.release();

            // test 2 - acquire try and check that lock throws OverlappingFileLockException
            long pos = rand.nextInt(Integer.MAX_VALUE);
            fl = ch.tryLock(pos, 0, false);
            long expectedSize = Long.MAX_VALUE - pos;
            if(fl.size() != expectedSize)
                throw new RuntimeException("Lock size " + fl.size() + " != " +
                    expectedSize + " for position " + pos);
            if (fl == null)
                throw new RuntimeException("Unable to acquire lock");
            try {
                ch.lock((Void)null, new CompletionHandler<FileLock,Void> () {
                    public void completed(FileLock result, Void att) {
                    }
                    public void failed(Throwable exc, Void att) {
                    }
                });
                throw new RuntimeException("OverlappingFileLockException expected");
            } catch (OverlappingFileLockException x) {
            }
        } finally {
            ch.close();
        }

        // test 3 - channel is closed so FileLock should no longer be valid
        if (fl.isValid())
            throw new RuntimeException("FileLock expected to be invalid");
    }

    // interrupt should not close channel
    static void testInterruptHandlerThread(final AsynchronousFileChannel ch) {
        System.out.println("testInterruptHandlerThread");

        ByteBuffer buf = ByteBuffer.allocateDirect(100);
        final CountDownLatch latch = new CountDownLatch(1);

        ch.read(buf, 0L, (Void)null, new CompletionHandler<Integer,Void>() {
            public void completed(Integer result, Void att) {
                try {
                    Thread.currentThread().interrupt();
                    long size = ch.size();
                    latch.countDown();
                } catch (IOException x) {
                    x.printStackTrace();
                }
            }
            public void failed(Throwable exc, Void att) {
            }
        });

        // wait for handler to complete
        await(latch);
    }

    // invoke method on closed channel
    static void testClosedChannel(AsynchronousFileChannel ch) {
        System.out.println("testClosedChannel");

        if (ch.isOpen())
            throw new RuntimeException("Channel should be closed");

        ByteBuffer buf = ByteBuffer.allocateDirect(100);

        // check read fails with ClosedChannelException
        try {
            ch.read(buf, 0L).get();
            throw new RuntimeException("ExecutionException expected");
        } catch (ExecutionException x) {
            if (!(x.getCause() instanceof ClosedChannelException))
                throw new RuntimeException("Cause of ClosedChannelException expected");
        } catch (InterruptedException x) {
        }

        // check write fails with ClosedChannelException
        try {
            ch.write(buf, 0L).get();
            throw new RuntimeException("ExecutionException expected");
        } catch (ExecutionException x) {
            if (!(x.getCause() instanceof ClosedChannelException))
                throw new RuntimeException("Cause of ClosedChannelException expected");
        } catch (InterruptedException x) {
        }

        // check lock fails with ClosedChannelException
        try {
            ch.lock().get();
            throw new RuntimeException("ExecutionException expected");
        } catch (ExecutionException x) {
            if (!(x.getCause() instanceof ClosedChannelException))
                throw new RuntimeException("Cause of ClosedChannelException expected");
        } catch (InterruptedException x) {
        }
    }


    // exercise custom thread pool
    static void testCustomThreadPool(Path file) throws IOException {
        System.out.println("testCustomThreadPool");

        // records threads that are created
        final List<Thread> threads = new ArrayList<Thread>();

        ThreadFactory threadFactory = new ThreadFactory() {
             @Override
             public Thread newThread(Runnable r) {
                 Thread t = new Thread(r);
                 t.setDaemon(true);
                 synchronized (threads) {
                     threads.add(t);
                 }
                 return t;
             }
        };

        // exercise tests with varied number of threads
        for (int nThreads=1; nThreads<=5; nThreads++) {
            synchronized (threads) {
                threads.clear();
            }
            ExecutorService executor = Executors.newFixedThreadPool(nThreads, threadFactory);
            Set<StandardOpenOption> opts = EnumSet.of(WRITE);
            AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, opts, executor);
            try {
                for (int i=0; i<10; i++) {
                    // do I/O operation to see which thread invokes the completion handler
                    final AtomicReference<Thread> invoker = new AtomicReference<Thread>();
                    final CountDownLatch latch = new CountDownLatch(1);

                    ch.write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
                        public void completed(Integer result, Void att) {
                            invoker.set(Thread.currentThread());
                            latch.countDown();
                        }
                        public void failed(Throwable exc, Void att) {
                        }
                    });
                    await(latch);

                    // check invoker
                    boolean found = false;
                    synchronized (threads) {
                        for (Thread t: threads) {
                            if (t == invoker.get()) {
                                found = true;
                                break;
                            }
                        }
                    }
                    if (!found)
                        throw new RuntimeException("Invoker thread not found");
                }
            } finally {
                ch.close();
                executor.shutdown();
            }
        }


        // test sharing a thread pool between many channels
        ExecutorService executor = Executors
            .newFixedThreadPool(1+rand.nextInt(10), threadFactory);
        final int n = 50 + rand.nextInt(50);
        AsynchronousFileChannel[] channels = new AsynchronousFileChannel[n];
        try {
            for (int i=0; i<n; i++) {
                Set<StandardOpenOption> opts = EnumSet.of(WRITE);
                channels[i] = AsynchronousFileChannel.open(file, opts, executor);
                final CountDownLatch latch = new CountDownLatch(1);
                channels[i].write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
                    public void completed(Integer result, Void att) {
                        latch.countDown();
                    }
                    public void failed(Throwable exc, Void att) {
                    }
                });
                await(latch);

                // close ~half the channels
                if (rand.nextBoolean())
                    channels[i].close();
            }
        } finally {
            // close remaining channels
            for (int i=0; i<n; i++) {
                if (channels[i] != null) channels[i].close();
            }
            executor.shutdown();
        }
    }

    // exercise asynchronous close
    static void testAsynchronousClose(Path file) throws IOException {
        System.out.println("testAsynchronousClose");

        // create file
        AsynchronousFileChannel ch = AsynchronousFileChannel
            .open(file, WRITE, TRUNCATE_EXISTING);
        long size = 0L;
        do {
            ByteBuffer buf = genBuffer();
            int n = buf.remaining();
            writeFully(ch, buf, size);
            size += n;
        } while (size < (50L * 1024L * 1024L));

        ch.close();

        ch = AsynchronousFileChannel.open(file, WRITE, SYNC);

        // randomize number of writers, buffer size, and positions

        int nwriters = 1 + rand.nextInt(8);
        ByteBuffer[] buf = new ByteBuffer[nwriters];
        long[] position = new long[nwriters];
        for (int i=0; i<nwriters; i++) {
            buf[i] = genBuffer();
            position[i] = rand.nextInt((int)size);
        }

        // initiate I/O
        Future[] result = new Future[nwriters];
        for (int i=0; i<nwriters; i++) {
            result[i] = ch.write(buf[i], position[i]);
        }

        // close file
        ch.close();

        // write operations should complete or fail with AsynchronousCloseException
        for (int i=0; i<nwriters; i++) {
            try {
                result[i].get();
            } catch (ExecutionException x) {
                Throwable cause = x.getCause();
                if (!(cause instanceof AsynchronousCloseException))
                    throw new RuntimeException(cause);
            } catch (CancellationException  x) {
                throw new RuntimeException(x);   // should not happen
            } catch (InterruptedException x) {
                throw new RuntimeException(x);   // should not happen
            }
        }
    }

    // exercise cancel method
    static void testCancel(Path file) throws IOException {
        System.out.println("testCancel");

        for (int i=0; i<2; i++) {
            boolean mayInterruptIfRunning = (i == 0) ? false : true;

            // open with SYNC option to improve chances that write will not
            // complete immediately
            AsynchronousFileChannel ch = AsynchronousFileChannel
                .open(file, WRITE, SYNC);

            // start write operation
            Future<Integer> res = ch.write(genBuffer(), 0L);

            // cancel operation
            boolean cancelled = res.cancel(mayInterruptIfRunning);

            // check post-conditions
            if (!res.isDone())
                throw new RuntimeException("isDone should return true");
            if (res.isCancelled() != cancelled)
                throw new RuntimeException("isCancelled not consistent");
            try {
                res.get();
                if (cancelled)
                    throw new RuntimeException("CancellationException expected");
            } catch (CancellationException x) {
                if (!cancelled)
                    throw new RuntimeException("CancellationException not expected");
            } catch (ExecutionException x) {
                throw new RuntimeException(x);
            } catch (InterruptedException x) {
                throw new RuntimeException(x);
            }
            try {
                res.get(1, TimeUnit.SECONDS);
                if (cancelled)
                    throw new RuntimeException("CancellationException expected");
            } catch (CancellationException x) {
                if (!cancelled)
                    throw new RuntimeException("CancellationException not expected");
            } catch (ExecutionException x) {
                throw new RuntimeException(x);
            } catch (TimeoutException x) {
                throw new RuntimeException(x);
            } catch (InterruptedException x) {
                throw new RuntimeException(x);
            }

            ch.close();
        }
    }

    // exercise truncate method
    static void testTruncate(Path file) throws IOException {
        System.out.println("testTruncate");

        // basic tests
        AsynchronousFileChannel ch = AsynchronousFileChannel
            .open(file, CREATE, WRITE, TRUNCATE_EXISTING);
        try {
            writeFully(ch, genBuffer(), 0L);
            long size = ch.size();

            // attempt to truncate to a size greater than the current size
            if (ch.truncate(size + 1L).size() != size)
                throw new RuntimeException("Unexpected size after truncation");

            // truncate file
            if (ch.truncate(size - 1L).size() != (size - 1L))
                throw new RuntimeException("Unexpected size after truncation");

            // invalid size
            try {
                ch.truncate(-1L);
                throw new RuntimeException("IllegalArgumentException expected");
            } catch (IllegalArgumentException e) { }

        } finally {
            ch.close();
        }

        // channel is closed
        try {
            ch.truncate(0L);
            throw new RuntimeException("ClosedChannelException expected");
        } catch (ClosedChannelException  e) { }

        // channel is read-only
        ch = AsynchronousFileChannel.open(file, READ);
        try {
            try {
            ch.truncate(0L);
                throw new RuntimeException("NonWritableChannelException expected");
            } catch (NonWritableChannelException  e) { }
        } finally {
            ch.close();
        }
    }

    // returns ByteBuffer with random bytes
    static ByteBuffer genBuffer() {
        int size = 1024 + rand.nextInt(16000);
        byte[] buf = new byte[size];
        return switch (rand.nextInt(3)) {
            case 0 -> ByteBuffer.allocateDirect(buf.length)
                    .put(buf)
                    .flip();
            case 1 -> ByteBuffer.wrap(buf);
            case 2 -> Arena.ofAuto().allocate(buf.length).asByteBuffer()
                    .put(buf)
                    .flip();
            default -> throw new InternalError("Should not reach here");
        };
    }

    // writes all remaining bytes in the buffer to the given channel at the
    // given position
    static void writeFully(final AsynchronousFileChannel ch,
                           final ByteBuffer src,
                           long position)
    {
        final CountDownLatch latch = new CountDownLatch(1);

        // use position as attachment
        ch.write(src, position, position, new CompletionHandler<Integer,Long>() {
            public void completed(Integer result, Long position) {
                int n = result;
                if (src.hasRemaining()) {
                    long p = position + n;
                    ch.write(src, p, p, this);
                } else {
                    latch.countDown();
                }
            }
            public void failed(Throwable exc, Long position) {
            }
        });

        // wait for writes to complete
        await(latch);
    }

    static void readAll(final AsynchronousFileChannel ch,
                        final ByteBuffer dst,
                       long position)
    {
        final CountDownLatch latch = new CountDownLatch(1);

        // use position as attachment
        ch.read(dst, position, position, new CompletionHandler<Integer,Long>() {
            public void completed(Integer result, Long position) {
                int n = result;
                if (n > 0) {
                    long p = position + n;
                    ch.read(dst, p, p, this);
                } else {
                    latch.countDown();
                }
            }
            public void failed(Throwable exc, Long position) {
            }
        });

        // wait for reads to complete
        await(latch);
    }

    static void await(CountDownLatch latch) {
        // wait until done
        boolean done = false;
        while (!done) {
            try {
                latch.await();
                done = true;
            } catch (InterruptedException x) { }
        }
    }
}
