/*
 * Copyright (c) 2008, 2009, 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
 * @summary Test Channels methods for interoperability between streams and
 *     asynchronous byte channels
 */

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

public class Basic2 {

    static final Random rand = new Random();

    public static void main(String[] args) throws Exception {
        // establish loopback connection
        AsynchronousServerSocketChannel listener =
            AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
        InetSocketAddress isa =
            new InetSocketAddress(InetAddress.getLocalHost(), port);
        AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open();
        ch1.connect(isa).get();
        AsynchronousSocketChannel ch2 = listener.accept().get();

        // start thread to write to stream
        Writer writer = new Writer(Channels.newOutputStream(ch1));
        Thread writerThread = new Thread(writer);
        writerThread.start();

        // start thread to read from stream
        Reader reader = new Reader(Channels.newInputStream(ch2));
        Thread readerThread = new Thread(reader);
        readerThread.start();

        // wait for threads to complete
        writerThread.join();
        readerThread.join();

        // check that reader received what we expected
        if (reader.total() != writer.total())
            throw new RuntimeException("Unexpected number of bytes read");
        if (reader.hash() != writer.hash())
            throw new RuntimeException("Hash incorrect for bytes read");

        // channels should be closed
        if (ch1.isOpen() || ch2.isOpen())
            throw new RuntimeException("Channels should be closed");
    }

    static class Reader implements Runnable {
        private final InputStream in;
        private volatile int total;
        private volatile int hash;

        Reader(InputStream in) {
            this.in = in;
        }

        public void run() {
            try {
                int n;
                do {
                    // random offset/len
                    byte[] buf = new byte[128 + rand.nextInt(128)];
                    int len, off;
                    if (rand.nextBoolean()) {
                        len = buf.length;
                        off = 0;
                        n = in.read(buf);
                    } else {
                        len = 1 + rand.nextInt(64);
                        off = rand.nextInt(64);
                        n = in.read(buf, off, len);
                    }
                    if (n > len)
                        throw new RuntimeException("Too many bytes read");
                    if (n > 0) {
                        total += n;
                        for (int i=0; i<n; i++) {
                            int value = buf[off + i];
                            hash = hash ^ value;
                        }
                    }
                } while (n > 0);
                in.close();

            } catch (IOException x) {
                x.printStackTrace();
            }
        }

        int total() { return total; }
        int hash() { return hash; }
    }

    static class Writer implements Runnable {
        private final OutputStream out;
        private final int total;
        private volatile int hash;

        Writer(OutputStream out) {
            this.out = out;
            this.total = 50*1000 + rand.nextInt(50*1000);
        }

        public void run() {
            hash = 0;
            int rem = total;
            try {
                do {
                    byte[] buf = new byte[1 + rand.nextInt(rem)];
                    int off, len;

                    // write random bytes
                    if (rand.nextBoolean()) {
                        off = 0;
                        len = buf.length;
                    } else {
                        off = rand.nextInt(buf.length);
                        int r = buf.length - off;
                        len = (r <= 1) ? 1 : (1 + rand.nextInt(r));
                    }
                    for (int i=0; i<len; i++) {
                        byte value = (byte)rand.nextInt(256);
                        buf[off + i] = value;
                        hash = hash ^ value;
                    }
                    if ((off == 0) && (len == buf.length)) {
                        out.write(buf);
                    } else {
                        out.write(buf, off, len);
                    }
                    rem -= len;
                } while (rem > 0);

                // close stream when done
                out.close();

            } catch (IOException x) {
                x.printStackTrace();
            }
        }

        int total() { return total; }
        int hash() { return hash; }
    }
}
