/*
 * Copyright (c) 2001, 2024, 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 4434723 4482726 4559072 4795550 5081340 5103988 6984545 8325382
 * @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed)
 * @library ..
 * @library /test/lib
 * @build jdk.test.lib.RandomFactory
 * @run testng/timeout=300 Transfer
 * @key randomness
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.Pipe;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.file.Files;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import jdk.test.lib.RandomFactory;

import org.testng.Assert;
import org.testng.annotations.Test;

public class Transfer {

    private static Random generator = RandomFactory.getRandom();

    @Test
    public void testFileChannel() throws Exception {
        File source = File.createTempFile("source", null);
        source.deleteOnExit();
        File sink = File.createTempFile("sink", null);
        sink.deleteOnExit();

        FileOutputStream fos = new FileOutputStream(source);
        FileChannel sourceChannel = fos.getChannel();
        sourceChannel.write(ByteBuffer.wrap(
            "Use the source, Luke!".getBytes()));
        sourceChannel.close();

        FileInputStream fis = new FileInputStream(source);
        sourceChannel = fis.getChannel();

        RandomAccessFile raf = new RandomAccessFile(sink, "rw");
        FileChannel sinkChannel = raf.getChannel();
        long oldSinkPosition = sinkChannel.position();
        long oldSourcePosition = sourceChannel.position();

        long bytesWritten = sinkChannel.transferFrom(sourceChannel, 0, 10);
        if (bytesWritten != 10)
            throw new RuntimeException("Transfer failed");

        if (sourceChannel.position() == oldSourcePosition)
            throw new RuntimeException("Source position didn't change");

        if (sinkChannel.position() != oldSinkPosition)
            throw new RuntimeException("Sink position changed");

        if (sinkChannel.size() != 10)
            throw new RuntimeException("Unexpected sink size");

        bytesWritten = sinkChannel.transferFrom(sourceChannel, 1000, 10);

        if (bytesWritten > 10)
            throw new RuntimeException("Wrote too many bytes");

        if (sinkChannel.size() != 1000 + bytesWritten)
            throw new RuntimeException("Unexpected sink size");

        sourceChannel.close();
        sinkChannel.close();

        source.delete();
        sink.delete();
    }

    @Test
    public void testReadableByteChannel() throws Exception {
        int[] testSizes = { 0, 10, 1023, 1024, 1025, 2047, 2048, 2049 };

        for (int size : testSizes) {
            SelectorProvider sp = SelectorProvider.provider();
            Pipe p = sp.openPipe();
            Pipe.SinkChannel sink = p.sink();
            Pipe.SourceChannel source = p.source();
            sink.configureBlocking(false);

            ByteBuffer outgoingdata = ByteBuffer.allocateDirect(size + 10);
            byte[] someBytes = new byte[size + 10];
            generator.nextBytes(someBytes);
            outgoingdata.put(someBytes);
            outgoingdata.flip();

            int totalWritten = 0;
            while (totalWritten < size + 10) {
                int written = sink.write(outgoingdata);
                if (written < 0)
                    throw new Exception("Write failed");
                totalWritten += written;
            }

            File f = File.createTempFile("blah"+size, null);
            f.deleteOnExit();
            RandomAccessFile raf = new RandomAccessFile(f, "rw");
            FileChannel fc = raf.getChannel();
            long oldPosition = fc.position();

            long bytesWritten = fc.transferFrom(source, 0, size);
            fc.force(true);
            if (bytesWritten != size)
                throw new RuntimeException("Transfer failed");

            if (fc.position() != oldPosition)
                throw new RuntimeException("Position changed");

            if (fc.size() != size)
                throw new RuntimeException("Unexpected sink size "+ fc.size());

            fc.close();
            sink.close();
            source.close();

            f.delete();
        }
    }

    @Test
    public void transferToNoThrow() throws IOException { // for bug 8325382
        File source = File.createTempFile("before", "after");
        source.deleteOnExit();

        CharSequence csq = "Reality is greater than the sum of its parts.";
        Files.writeString(source.toPath(), csq);
        final long length = csq.length();
        Assert.assertEquals(source.length(), length);

        File target = File.createTempFile("before", "after");
        target.deleteOnExit();

        try (FileInputStream in = new FileInputStream(source);
             FileOutputStream out = new FileOutputStream(target);
             FileChannel chSource = in.getChannel();
             FileChannel chTarget = out.getChannel()) {
            // The count of bytes requested to transfer must exceed
            // FileChannelImpl.MAPPED_TRANSFER_THRESHOLD which is
            // currently 16384
            long n = chSource.transferTo(length, 16385, chTarget);

            // At the end of the input so no bytes should be transferred
            Assert.assertEquals(n, 0);
        }
    }

    @Test
    public void xferTest02() throws Exception { // for bug 4482726
        byte[] srcData = new byte[5000];
        for (int i=0; i<5000; i++)
            srcData[i] = (byte)generator.nextInt();

        // get filechannel for the source file.
        File source = File.createTempFile("source", null);
        source.deleteOnExit();
        RandomAccessFile raf1 = new RandomAccessFile(source, "rw");
        FileChannel fc1 = raf1.getChannel();

        // write out data to the file channel
        long bytesWritten = 0;
        while (bytesWritten < 5000) {
            bytesWritten = fc1.write(ByteBuffer.wrap(srcData));
        }

        // get filechannel for the dst file.
        File dest = File.createTempFile("dest", null);
        dest.deleteOnExit();
        RandomAccessFile raf2 = new RandomAccessFile(dest, "rw");
        FileChannel fc2 = raf2.getChannel();

        int bytesToWrite = 3000;
        int startPosition = 1000;

        bytesWritten = fc1.transferTo(startPosition, bytesToWrite, fc2);

        fc1.close();
        fc2.close();
        raf1.close();
        raf2.close();

        source.delete();
        dest.delete();
    }

    @Test
    public void xferTest03() throws Exception { // for bug 4559072
        byte[] srcData = new byte[] {1,2,3,4} ;

        // get filechannel for the source file.
        File source = File.createTempFile("source", null);
        source.deleteOnExit();
        RandomAccessFile raf1 = new RandomAccessFile(source, "rw");
        FileChannel fc1 = raf1.getChannel();
        fc1.truncate(0);

        // write out data to the file channel
        int bytesWritten = 0;
        while (bytesWritten < 4) {
            bytesWritten = fc1.write(ByteBuffer.wrap(srcData));
        }

        // get filechannel for the dst file.
        File dest = File.createTempFile("dest", null);
        dest.deleteOnExit();
        RandomAccessFile raf2 = new RandomAccessFile(dest, "rw");
        FileChannel fc2 = raf2.getChannel();
        fc2.truncate(0);

        fc1.transferTo(0, srcData.length + 1, fc2);

        if (fc2.size() > 4)
            throw new Exception("xferTest03 failed");

        fc1.close();
        fc2.close();
        raf1.close();
        raf2.close();

        source.delete();
        dest.delete();
    }

    // xferTest04() and xferTest05() moved to Transfer4GBFile.java

    static void checkFileData(File file, String expected) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        Reader r = new BufferedReader(new InputStreamReader(fis, "ASCII"));
        StringBuilder sb = new StringBuilder();
        int c;
        while ((c = r.read()) != -1)
            sb.append((char)c);
        String contents = sb.toString();
        if (! contents.equals(expected))
            throw new Exception("expected: " + expected
                                + ", got: " + contents);
        r.close();
    }

    // Test transferFrom asking for more bytes than remain in source
    @Test
    public void xferTest06() throws Exception { // for bug 5081340
        String data = "Use the source, Luke!";

        File source = File.createTempFile("source", null);
        source.deleteOnExit();
        File sink = File.createTempFile("sink", null);
        sink.deleteOnExit();

        FileOutputStream fos = new FileOutputStream(source);
        fos.write(data.getBytes("ASCII"));
        fos.close();

        FileChannel sourceChannel =
            new RandomAccessFile(source, "rw").getChannel();
        sourceChannel.position(7);
        long remaining = sourceChannel.size() - sourceChannel.position();
        FileChannel sinkChannel =
            new RandomAccessFile(sink, "rw").getChannel();
        long n = sinkChannel.transferFrom(sourceChannel, 0L,
                                          sourceChannel.size()); // overflow
        if (n != remaining)
            throw new Exception("n == " + n + ", remaining == " + remaining);

        sinkChannel.close();
        sourceChannel.close();

        checkFileData(source, data);
        checkFileData(sink, data.substring(7,data.length()));

        source.delete();
    }

    // Test transferTo to non-blocking socket channel
    @Test
    public void xferTest07() throws Exception { // for bug 5103988
        File source = File.createTempFile("source", null);
        source.deleteOnExit();

        FileChannel sourceChannel = new RandomAccessFile(source, "rw")
            .getChannel();
        sourceChannel.position(32000L)
            .write(ByteBuffer.wrap("The End".getBytes()));

        // The sink is a non-blocking socket channel
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.socket().bind(new InetSocketAddress(0));
        InetSocketAddress sa = new InetSocketAddress(
            InetAddress.getLocalHost(), ssc.socket().getLocalPort());
        SocketChannel sink = SocketChannel.open(sa);
        sink.configureBlocking(false);
        SocketChannel other = ssc.accept();

        long size = sourceChannel.size();

        // keep sending until congested
        long n;
        do {
            n = sourceChannel.transferTo(0, size, sink);
        } while (n > 0);

        sourceChannel.close();
        sink.close();
        other.close();
        ssc.close();
        source.delete();
    }

    // xferTest08() moved to TransferTo6GBFile.java

    // Test that transferFrom with FileChannel source that is not readable
    // throws NonReadableChannelException
    @Test
    public void xferTest09() throws Exception { // for bug 6984545
        File source = File.createTempFile("source", null);
        source.deleteOnExit();

        File target = File.createTempFile("target", null);
        target.deleteOnExit();

        FileChannel fc1 = new FileOutputStream(source).getChannel();
        FileChannel fc2 = new RandomAccessFile(target, "rw").getChannel();
        try {
            fc2.transferFrom(fc1, 0L, 0);
            throw new RuntimeException("NonReadableChannelException expected");
        } catch (NonReadableChannelException expected) {
        } finally {
            fc1.close();
            fc2.close();
        }
    }
}
