2009-02-15 12:25:54 +00:00
|
|
|
/*
|
2010-12-28 23:53:50 +00:00
|
|
|
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
2009-02-15 12:25:54 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2010-05-25 22:58:33 +00:00
|
|
|
* 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.
|
2009-02-15 12:25:54 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* @test
|
|
|
|
* @bug 4607272
|
|
|
|
* @summary Unit test for AsynchronousChannelGroup
|
|
|
|
* @build Basic
|
|
|
|
* @run main/othervm -XX:-UseVMInterruptibleIO Basic
|
|
|
|
*/
|
|
|
|
|
|
|
|
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 = new ThreadFactory() {
|
|
|
|
@Override
|
|
|
|
public Thread newThread(final Runnable r) {
|
|
|
|
return new Thread(r);
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
shutdownTests();
|
|
|
|
shutdownNowTests();
|
|
|
|
afterShutdownTests();
|
|
|
|
miscTests();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void shutdownTests() throws Exception {
|
|
|
|
System.out.println("-- test shutdown --");
|
|
|
|
|
|
|
|
// test shutdown with no channels in groups
|
|
|
|
for (int i=0; i<500; i++) {
|
|
|
|
ExecutorService pool = null;
|
|
|
|
AsynchronousChannelGroup group;
|
|
|
|
if (rand.nextBoolean()) {
|
|
|
|
pool = Executors.newCachedThreadPool();
|
|
|
|
group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5));
|
|
|
|
} else {
|
|
|
|
int nThreads = 1 + rand.nextInt(8);
|
|
|
|
group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, threadFactory);
|
|
|
|
}
|
|
|
|
group.shutdown();
|
|
|
|
if (!group.isShutdown())
|
|
|
|
throw new RuntimeException("Group should be shutdown");
|
|
|
|
// group should terminate quickly
|
|
|
|
boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
|
|
|
|
if (!terminated)
|
|
|
|
throw new RuntimeException("Group should have terminated");
|
|
|
|
if (pool != null && !pool.isTerminated())
|
|
|
|
throw new RuntimeException("Executor should have terminated");
|
|
|
|
}
|
|
|
|
|
|
|
|
// shutdown with channel in group
|
|
|
|
for (int i=0; i<500; i++) {
|
|
|
|
ExecutorService pool = null;
|
|
|
|
AsynchronousChannelGroup group;
|
|
|
|
if (rand.nextBoolean()) {
|
|
|
|
pool = Executors.newCachedThreadPool();
|
|
|
|
group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(10));
|
|
|
|
} else {
|
|
|
|
int nThreads = 1 + rand.nextInt(8);
|
|
|
|
group = AsynchronousChannelGroup.withFixedThreadPool(nThreads, threadFactory);
|
|
|
|
}
|
|
|
|
// create channel that is bound to group
|
|
|
|
AsynchronousChannel ch;
|
2010-11-02 10:05:42 +00:00
|
|
|
switch (rand.nextInt(2)) {
|
2009-02-15 12:25:54 +00:00
|
|
|
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
|
|
|
|
boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
|
|
|
|
if (!terminated)
|
|
|
|
throw new RuntimeException("Group should have terminated");
|
|
|
|
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 = null;
|
|
|
|
AsynchronousChannelGroup group;
|
|
|
|
if (rand.nextBoolean()) {
|
|
|
|
pool = Executors.newCachedThreadPool();
|
|
|
|
group = AsynchronousChannelGroup
|
|
|
|
.withCachedThreadPool(pool, rand.nextInt(5));
|
|
|
|
} else {
|
|
|
|
int nThreads = 1 + rand.nextInt(8);
|
|
|
|
group = AsynchronousChannelGroup
|
|
|
|
.withFixedThreadPool(nThreads, threadFactory);
|
|
|
|
}
|
|
|
|
|
|
|
|
// I/O in progress
|
2010-11-02 10:05:42 +00:00
|
|
|
AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel
|
|
|
|
.open(group).bind(new InetSocketAddress(0));
|
|
|
|
ch.accept();
|
2009-02-15 12:25:54 +00:00
|
|
|
|
|
|
|
// forceful shutdown
|
|
|
|
group.shutdownNow();
|
|
|
|
|
|
|
|
// shutdownNow is required to close all channels
|
|
|
|
if (ch.isOpen())
|
|
|
|
throw new RuntimeException("Channel should be closed");
|
|
|
|
|
|
|
|
boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
|
|
|
|
if (!terminated)
|
|
|
|
throw new RuntimeException("Group should have terminated");
|
|
|
|
if (pool != null && !pool.isTerminated())
|
|
|
|
throw new RuntimeException("Executor should have terminated");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
terminated = group.awaitTermination(3, TimeUnit.SECONDS);
|
|
|
|
if (!terminated)
|
|
|
|
throw new RuntimeException("Group should have terminated");
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|