/*
 * Copyright (c) 2008, 2012, 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 Unit test for AsynchronousChannelGroup
 */

import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.io.IOException;

public class Basic {
    static final Random rand = new Random();
    static final ThreadFactory threadFactory = (Runnable r) -> {
        return new Thread(r);
    };

    public static void main(String[] args) throws Exception {
        shutdownTests();
        shutdownNowTests();
        afterShutdownTests();
        miscTests();
    }

    static void awaitTermination(AsynchronousChannelGroup group) throws InterruptedException {
        boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
        if (!terminated)
            throw new RuntimeException("Group should have terminated");
    }

    static void testShutdownWithNoChannels(ExecutorService pool,
                                           AsynchronousChannelGroup group)
        throws Exception
    {
        group.shutdown();
        if (!group.isShutdown())
            throw new RuntimeException("Group should be shutdown");
        // group should terminate quickly
        awaitTermination(group);
        if (pool != null && !pool.isTerminated())
            throw new RuntimeException("Executor should have terminated");
    }

    static void testShutdownWithChannels(ExecutorService pool,
                                         AsynchronousChannelGroup group)
        throws Exception
    {

        // create channel that is bound to group
        AsynchronousChannel ch;
        switch (rand.nextInt(2)) {
            case 0 : ch = AsynchronousSocketChannel.open(group); break;
            case 1 : ch = AsynchronousServerSocketChannel.open(group); break;
            default : throw new AssertionError();
        }
        group.shutdown();
        if (!group.isShutdown())
            throw new RuntimeException("Group should be shutdown");

        // last channel so should terminate after this channel is closed
        ch.close();

        // group should terminate quickly
        awaitTermination(group);
        if (pool != null && !pool.isTerminated())
            throw new RuntimeException("Executor should have terminated");
    }

    static void shutdownTests() throws Exception {
        System.out.println("-- test shutdown --");

        // test shutdown with no channels in groups
        for (int i = 0; i < 100; i++) {
            ExecutorService pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withCachedThreadPool(pool, rand.nextInt(5));
            testShutdownWithNoChannels(pool, group);
        }
        for (int i = 0; i < 100; i++) {
            int nThreads = 1 + rand.nextInt(8);
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withFixedThreadPool(nThreads, threadFactory);
            testShutdownWithNoChannels(null, group);
        }
        for (int i = 0; i < 100; i++) {
            ExecutorService pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withThreadPool(pool);
            testShutdownWithNoChannels(pool, group);
        }

        // test shutdown with channel in group
        for (int i = 0; i < 100; i++) {
            ExecutorService pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withCachedThreadPool(pool, rand.nextInt(10));
            testShutdownWithChannels(pool, group);
        }
        for (int i = 0; i < 100; i++) {
            int nThreads = 1 + rand.nextInt(8);
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withFixedThreadPool(nThreads, threadFactory);
            testShutdownWithChannels(null, group);
        }
        for (int i = 0; i < 100; i++) {
            ExecutorService pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withThreadPool(pool);
            testShutdownWithChannels(pool, group);
        }
    }

    static void testShutdownNow(ExecutorService pool,
                                AsynchronousChannelGroup group)
        throws Exception
    {
        // I/O in progress
        AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel
                .open(group).bind(new InetSocketAddress(0));
        ch.accept();

        // forceful shutdown
        group.shutdownNow();

        // shutdownNow is required to close all channels
        if (ch.isOpen())
            throw new RuntimeException("Channel should be closed");

        awaitTermination(group);

        if (pool != null && !pool.isTerminated())
            throw new RuntimeException("Executor should have terminated");
    }

    static void shutdownNowTests() throws Exception {
        System.out.println("-- test shutdownNow --");

        for (int i = 0; i < 10; i++) {
            ExecutorService pool = pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withCachedThreadPool(pool, rand.nextInt(5));
            testShutdownNow(pool, group);
        }
        for (int i = 0; i < 10; i++) {
            int nThreads = 1 + rand.nextInt(8);
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withFixedThreadPool(nThreads, threadFactory);
            testShutdownNow(null, group);
        }
        for (int i = 0; i < 10; i++) {
            ExecutorService pool = Executors.newCachedThreadPool();
            AsynchronousChannelGroup group = AsynchronousChannelGroup
                    .withThreadPool(pool);
            testShutdownNow(pool, group);
        }
    }

    // test creating channels in group after group is shutdown
    static void afterShutdownTests() throws Exception {
        System.out.println("-- test operations after group is shutdown  --");
        AsynchronousChannelGroup group =
            AsynchronousChannelGroup.withFixedThreadPool(1, threadFactory);

        AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group);
        AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open(group);

        // initiate accept
        listener.bind(new InetSocketAddress(0));
        Future<AsynchronousSocketChannel> result = listener.accept();

        // shutdown group
        group.shutdown();
        if (!group.isShutdown())
            throw new RuntimeException("Group should be shutdown");

        // attempt to create another channel
        try {
            AsynchronousSocketChannel.open(group);
            throw new RuntimeException("ShutdownChannelGroupException expected");
        } catch (ShutdownChannelGroupException x) {
        }
        try {
            AsynchronousServerSocketChannel.open(group);
            throw new RuntimeException("ShutdownChannelGroupException expected");
        } catch (ShutdownChannelGroupException x) {
        }

        // attempt to create another channel by connecting. This should cause
        // the accept operation to fail.
        InetAddress lh = InetAddress.getLocalHost();
        int port = ((InetSocketAddress)listener.getLocalAddress()).getPort();
        InetSocketAddress isa = new InetSocketAddress(lh, port);
        ch.connect(isa).get();
        try {
            result.get();
            throw new RuntimeException("Connection was accepted");
        } catch (ExecutionException x) {
            Throwable cause = x.getCause();
            if (!(cause instanceof IOException))
                throw new RuntimeException("Cause should be IOException");
            cause = cause.getCause();
            if (!(cause instanceof ShutdownChannelGroupException))
                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
        }

        // initiate another accept even though channel group is shutdown.
        Future<AsynchronousSocketChannel> res = listener.accept();
        try {
            res.get(3, TimeUnit.SECONDS);
            throw new RuntimeException("TimeoutException expected");
        } catch (TimeoutException x) {
        }
        // connect to the listener which should cause the accept to complete
        AsynchronousSocketChannel.open().connect(isa);
        try {
            res.get();
            throw new RuntimeException("Connection was accepted");
        } catch (ExecutionException x) {
            Throwable cause = x.getCause();
            if (!(cause instanceof IOException))
                throw new RuntimeException("Cause should be IOException");
            cause = cause.getCause();
            if (!(cause instanceof ShutdownChannelGroupException))
                throw new RuntimeException("IOException cause should be ShutdownChannelGroupException");
        }

        // group should *not* terminate as channels are open
        boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
        if (terminated)
            throw new RuntimeException("Group should not have terminated");

        // close channel; group should terminate quickly
        ch.close();
        listener.close();
        awaitTermination(group);
    }

    static void miscTests() throws Exception {
        System.out.println("-- miscellenous tests --");
        try {
            AsynchronousChannelGroup.withFixedThreadPool(1, null);
            throw new RuntimeException("NPE expected");
        } catch (NullPointerException x) {
        }
        try {
            AsynchronousChannelGroup.withFixedThreadPool(0, threadFactory);
            throw new RuntimeException("IAE expected");
        } catch (IllegalArgumentException e) {
        }
        try {
            AsynchronousChannelGroup.withCachedThreadPool(null, 0);
            throw new RuntimeException("NPE expected");
        } catch (NullPointerException x) {
        }
        try {
            AsynchronousChannelGroup.withThreadPool(null);
            throw new RuntimeException("NPE expected");
        } catch (NullPointerException e) {
        }
    }
}
