/*
 * Copyright (c) 2002, 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
 * @summary Comprehensive test for FileChannel.transfer{From,To}
 * @bug 4708120
 * @author Mark Reinhold
 */

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;


public class Transfers {

    static PrintStream out = System.out;

    private static class Failure
        extends RuntimeException
    {

        Failure(Exception x) {
            super(x);
        }

        Failure(String s) {
            super(s);
        }

    }


    // -- Writing and reading random bytes --

    private static void writeBytes(byte[] ba, FileChannel fc,
                                   int off, int len)
        throws IOException
    {
        fc.position(off);
        if (fc.write(ByteBuffer.wrap(ba, 0, len)) != len)
            throw new IOException("Incomplete write");
        fc.position(0);
    }

    private static void writeRandomBytes(long seed,
                                         FileChannel fc, int off, int len)
        throws IOException
    {
        Random r = new Random(seed);
        byte[] ba = new byte[len];
        r.nextBytes(ba);
        writeBytes(ba, fc, off, len);
    }

    private static void writeZeroBytes(FileChannel fc, int off, int len)
        throws IOException
    {
        byte[] ba = new byte[len];
        writeBytes(ba, fc, off, len);
    }

    private static void checkBytes(FileChannel fc, int off, int len,
                                   byte[] bytes)
        throws IOException
    {
        ByteBuffer bb = ByteBuffer.allocate(len);
        fc.position(off);
        if (fc.read(bb) != len)
            throw new IOException("Incomplete read");
        bb.flip();
        ByteBuffer bab = ByteBuffer.wrap(bytes, 0, len);
        if (!bb.equals(bab))
            throw new Failure("Wrong data written");
    }

    private static void checkRandomBytes(FileChannel fc, int off, int len,
                                         long seed)
        throws IOException
    {
        byte[] ba = new byte[len];
        Random r = new Random(seed);
        r.nextBytes(ba);
        checkBytes(fc, off, len, ba);
    }

    private static void checkZeroBytes(FileChannel fc, int off, int len)
        throws IOException
    {
        byte[] ba = new byte[len];
        checkBytes(fc, off, len, ba);
    }

    // For debugging
    //
    private static void dump(FileChannel fc)
        throws IOException
    {
        int sz = (int)fc.size();
        ByteBuffer bb = ByteBuffer.allocate(sz);
        fc.position(0);
        if (fc.read(bb) != sz)
            throw new IOException("Incomplete read");
        bb.flip();
        byte prev = -1;
        int r = 0;                      // Repeats
        int n = 0;
        while (bb.hasRemaining() && (n < 32)) {
            byte b = bb.get();
            if (b == prev) {
                r++;
                continue;
            }
            if (r > 0) {
                int c = prev & 0xff;
                if (c < 0x10)
                    out.print('0');
                out.print(Integer.toHexString(c));
                if (r > 1) {
                    out.print("[");
                    out.print(r);
                    out.print("]");
                }
                n++;
            }
            prev = b;
            r = 1;
        }
        if (r > 0) {
            int c = prev & 0xff;
            if (c < 0x10)
                out.print('0');
            out.print(Integer.toHexString(c));
            if (r > 1) {
                out.print("[");
                out.print(r);
                out.print("]");
            }
            n++;
        }
        if (bb.hasRemaining())
            out.print("...");
        out.println();
    }



    static File sourceFile;
    static File targetFile;

    // -- Self-verifying sources and targets --

    static abstract class Source {

        protected final int size;
        protected final long seed;
        private final String name;

        Source(int size, long seed, String name) {
            this.size = size;
            this.seed = seed;
            this.name = name;
        }

        String name() {
            return name;
        }

        abstract ReadableByteChannel channel();

        abstract void verify() throws IOException;

    }

    static class FileSource
        extends Source
    {
        private final File fn;
        private final RandomAccessFile raf;
        private final FileChannel fc;

        FileSource(int size, long seed) throws IOException {
            super(size, seed, "FileChannel");
            fn = sourceFile;
            raf = new RandomAccessFile(fn, "rw");
            fc = raf.getChannel();
            fc.position(0);
            writeRandomBytes(seed, fc, 0, size);
        }

        ReadableByteChannel channel() {
            return fc;
        }

        void verify() throws IOException {
            if (fc.position() != size)
                throw new Failure("Wrong position: "
                                  + fc.position() + " (expected " + size +
                                  ")");
            checkRandomBytes(fc, 0, size, seed);
            fc.close();
            raf.close();                // Bug in 1.4.0
        }

    }

    static class UserSource
        extends Source
    {
        private ReadableByteChannel ch;
        private final ByteBuffer src;

        UserSource(int size, long seed) {
            super(size, seed, "UserChannel");

            final byte[] bytes = new byte[size + 1];
            Random r = new Random(seed);
            r.nextBytes(bytes);
            src = ByteBuffer.wrap(bytes);

            ch = new ReadableByteChannel() {
                    public int read(ByteBuffer dst) {
                        if (!src.hasRemaining())
                            return -1;
                        int nr = Math.min(src.remaining(), dst.remaining());
                        ByteBuffer s = src.duplicate();
                        s.limit(s.position() + nr);
                        dst.put(s);
                        src.position(src.position() + nr);
                        return nr;
                    }
                    public boolean isOpen() {
                        return true;
                    }
                    public void close() { }
                };
        }

        ReadableByteChannel channel() {
            return ch;
        }

        void verify() {
            if (src.remaining() != 1)
                throw new Failure("Source has " + src.remaining()
                                  + " bytes remaining (expected 1)");
        }

    }

    static abstract class Target {

        protected final int size;
        protected final long seed;
        private final String name;

        Target(int size, long seed, String name) {
            this.size = size;
            this.seed = seed;
            this.name = name;
        }

        String name() {
            return name;
        }

        abstract WritableByteChannel channel();

        abstract void verify() throws IOException;

    }

    static class FileTarget
        extends Target
    {
        private final File fn;
        private final RandomAccessFile raf;
        private final FileChannel fc;

        FileTarget(int size, long seed) throws IOException {
            super(size, seed, "FileChannel");
            fn = targetFile;
            raf = new RandomAccessFile(fn, "rw");
            fc = raf.getChannel();
            fc.position(0);
        }

        WritableByteChannel channel() {
            return fc;
        }

        void verify() throws IOException {
            if (fc.position() != size)
                throw new Failure("Wrong position: "
                                  + fc.position() + " (expected " + size + ")");
            checkRandomBytes(fc, 0, size, seed);
            fc.close();
            raf.close();                // Bug in 1.4.0
        }

    }

    static class UserTarget
        extends Target
    {
        private WritableByteChannel ch;
        private final ByteBuffer dst;

        UserTarget(int size, long seed) {
            super(size, seed, "UserChannel");
            dst = ByteBuffer.wrap(new byte[size + 1]);

            ch = new WritableByteChannel() {
                    public int write(ByteBuffer src) {
                        int nr = Math.min(src.remaining(), dst.remaining());
                        ByteBuffer s = src.duplicate();
                        s.limit(s.position() + nr);
                        dst.put(s);
                        src.position(src.position() + nr);
                        return nr;
                    }
                    public boolean isOpen() {
                        return true;
                    }
                    public void close() { }
                };
        }

        WritableByteChannel channel() {
            return ch;
        }

        void verify() {
            if (dst.remaining() != 1)
                throw new Failure("Destination has " + dst.remaining()
                                  + " bytes remaining (expected 1)");
            byte[] ba = new byte[size];
            Random r = new Random(seed);
            r.nextBytes(ba);
            dst.flip();
            ByteBuffer rbb = ByteBuffer.wrap(ba, 0, size);
            if (!dst.equals(rbb))
                throw new Failure("Wrong data written");
        }

    }


    // Generates a sequence of ints of the form 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
    // 15, 16, 17, 31, 32, 33, ..., 2^i-1, 2^i, 2^i+1, ..., max.

    static class IntGenerator {

        private int max;
        private int cur = -1;
        private int p2 = 8;

        IntGenerator(int max) {
            this.max = max;
        }

        boolean hasNext() {
            return cur < max;
        }

        int next() {
            if (cur >= max)
                throw new IllegalStateException();
            if (cur < 6) {
                cur++;
                return cur;
            }
            if (cur == p2 + 1) {
                p2 <<= 1;
                cur = p2 - 1;
                return cur;
            }
            cur++;
            return cur;
        }

    }


    // -- Tests --

    private static final int MAX_XFER_SIZE = 1 << 14;
    private static final int MAX_FILE_SIZE = MAX_XFER_SIZE << 1;

    private static boolean debug = false;
    private static boolean verbose = false;

    static void show(String dir, String channelName, int off, int len) {
        if (!verbose)
            return;
        out.println(dir + " " + channelName +
                    ": offset " + off + ", length " + len);
    }

    static void testTo(long seed, FileChannel fc, int off, int len, Target tgt)
        throws IOException
    {
        show("To", tgt.name(), off, len);

        // Clear source, then randomize just the source region
        writeZeroBytes(fc, 0, MAX_FILE_SIZE);
        writeRandomBytes(seed, fc, off, len);

        // Randomize position
        int pos = (int)seed & 0xfff;
        fc.position(pos);

        int n = (int)fc.transferTo(off, len, tgt.channel());
        if (n != len)
            throw new Failure("Incorrect transfer length: " + n
                              + " (expected " + len + ")");

        // Check that source wasn't changed
        if (fc.position() != pos)
            throw new Failure("Position changed");
        if (debug)
            dump(fc);
        checkRandomBytes(fc, off, len, seed);
        writeZeroBytes(fc, off, len);
        checkZeroBytes(fc, 0, MAX_FILE_SIZE);

        // Check that target was updated correctly
        tgt.verify();
    }

    static void testFrom(long seed, Source src, FileChannel fc, int off, int len)
        throws IOException
    {
        show("From", src.name(), off, len);

        // Clear target
        writeZeroBytes(fc, 0, MAX_FILE_SIZE);

        // Randomize position
        int pos = (int)seed & 0xfff;
        fc.position(pos);

        int n = (int)fc.transferFrom(src.channel(), off, len);
        if (n != len)
            throw new Failure("Incorrect transfer length: " + n
                              + " (expected " + len + ")");

        // Check that source didn't change, and was read correctly
        src.verify();

        // Check that target was updated correctly
        if (fc.position() != pos)
            throw new Failure("Position changed");
        if (debug)
            dump(fc);
        checkRandomBytes(fc, off, len, seed);
        writeZeroBytes(fc, off, len);
        checkZeroBytes(fc, 0, MAX_FILE_SIZE);
    }

    public static void main(String[] args)
        throws Exception
    {
        if (args.length > 0) {
            if (args[0].indexOf('v') >= 0)
                verbose = true;
            if (args[0].indexOf('d') >= 0)
                debug = verbose = true;
        }

        sourceFile = File.createTempFile("xfer.src.", "");
        sourceFile.deleteOnExit();
        targetFile = File.createTempFile("xfer.tgt.", "");
        targetFile.deleteOnExit();

        File fn = File.createTempFile("xfer.fch.", "");
        fn.deleteOnExit();
        FileChannel fc = new RandomAccessFile(fn, "rw").getChannel();

        Random rnd = new Random();
        int failures = 0;

        for (boolean to = false;; to = true) {
            for (boolean user = false;; user = true) {
                if (!verbose)
                    out.print((to ? "To " : "From ") +
                              (user ? "user channel" : "file channel")
                              + ":");
                IntGenerator offGen = new IntGenerator(MAX_XFER_SIZE + 2);
                while (offGen.hasNext()) {
                    int off = offGen.next();
                    if (!verbose) out.print(" " + off);
                    IntGenerator lenGen = new IntGenerator(MAX_XFER_SIZE + 2);
                    while (lenGen.hasNext()) {
                        int len = lenGen.next();
                        long s = rnd.nextLong();
                        String chName = null;
                        try {
                            if (to) {
                                Target tgt;
                                if (user)
                                    tgt = new UserTarget(len, s);
                                else
                                    tgt = new FileTarget(len, s);
                                chName = tgt.name();
                                testTo(s, fc, off, len, tgt);
                            }
                            else {
                                Source src;
                                if (user)
                                    src = new UserSource(len, s);
                                else
                                    src = new FileSource(len, s);
                                chName = src.name();
                                testFrom(s, src, fc, off, len);
                            }
                        } catch (Failure x) {
                            out.println();
                            out.println("FAILURE: " + chName
                                        + ", offset " + off
                                        + ", length " + len);
                            x.printStackTrace(out);
                            failures++;
                        }
                    }
                }
                if (!verbose)
                    out.println();
                if (user)
                    break;
            }
            if (to)
                break;
        }

        if (failures > 0) {
            out.println();
            throw new RuntimeException("Some tests failed");
        }

    }

}
