Path: blob/master/test/jdk/java/nio/channels/SocketChannel/ConnectState.java
41154 views
/*1* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @summary Test socket-channel connection-state transitions25* @library .. /test/lib26* @build jdk.test.lib.Utils TestServers27* @run main ConnectState28*/2930import java.io.*;31import java.net.*;32import java.nio.*;33import java.nio.channels.*;34import java.util.Arrays;35import java.util.Collection;36import java.util.Collections;37import java.util.HashSet;383940public class ConnectState {4142static PrintStream log = System.err;4344static InetSocketAddress remote;4546final static int ST_UNCONNECTED = 0;47final static int ST_PENDING = 1;48final static int ST_CONNECTED = 2;49final static int ST_CLOSED = 3;50final static int ST_PENDING_OR_CONNECTED = 4;51// NO exceptions expected52final static Collection<Class<?>> NONE = Collections.emptySet();5354// make a set of expected exception.55static Collection<Class<?>> expectedExceptions(Class<?>... expected) {56final Collection<Class<?>> exceptions;57if (expected.length == 0) {58exceptions = NONE;59} else if (expected.length == 1) {60assert expected[0] != null;61exceptions = Collections.<Class<?>>singleton(expected[0]);62} else {63exceptions = new HashSet<>(Arrays.asList(expected));64}65return exceptions;66}6768static abstract class Test {6970abstract String go(SocketChannel sc) throws Exception;7172static void check(boolean test, String desc) throws Exception {73if (!test)74throw new Exception("Incorrect state: " + desc);75}7677static void check(SocketChannel sc, int state) throws Exception {78switch (state) {79case ST_UNCONNECTED:80check(!sc.isConnected(), "!isConnected");81check(!sc.isConnectionPending(), "!isConnectionPending");82check(sc.isOpen(), "isOpen");83break;84case ST_PENDING:85check(!sc.isConnected(), "!isConnected");86check(sc.isConnectionPending(), "isConnectionPending");87check(sc.isOpen(), "isOpen");88break;89case ST_CONNECTED:90check(sc.isConnected(), "isConnected");91check(!sc.isConnectionPending(), "!isConnectionPending");92check(sc.isOpen(), "isOpen");93break;94case ST_CLOSED:95check(sc.isConnected(), "isConnected");96check(!sc.isConnectionPending(), "!isConnectionPending");97check(sc.isOpen(), "isOpen");98break;99case ST_PENDING_OR_CONNECTED:100check(sc.isConnected() || sc.isConnectionPending(),101"isConnected || isConnectionPending");102check(sc.isOpen(), "isOpen");103break;104}105}106107Test(String name, Class<?> exception, int state) throws Exception {108this(name, expectedExceptions(exception), state);109}110111// On some architecture we may need to accept several exceptions.112// For instance on Solaris, when using a server colocated on the113// machine we cannot guarantee that we will get a114// ConnectionPendingException when connecting twice on the same115// non-blocking socket. We may instead get a an116// AlreadyConnectedException, which is also valid: it simply means117// that the first connection has been immediately accepted.118Test(String name, Collection<Class<?>> exceptions, int state)119throws Exception {120SocketChannel sc = SocketChannel.open();121String note;122try {123try {124note = go(sc);125} catch (Exception x) {126Class<?> expectedExceptionClass = null;127for (Class<?> exception : exceptions) {128if (exception.isInstance(x)) {129log.println(name + ": As expected: "130+ x);131expectedExceptionClass = exception;132check(sc, state);133break;134}135}136if (expectedExceptionClass == null137&& !exceptions.isEmpty()) {138// we had an exception, but it's not of the set of139// exceptions we expected.140throw new Exception(name141+ ": Incorrect exception",142x);143} else if (exceptions.isEmpty()) {144// we didn't expect any exception145throw new Exception(name146+ ": Unexpected exception",147x);148}149// if we reach here, we have our expected exception150assert expectedExceptionClass != null;151return;152}153if (!exceptions.isEmpty()) {154throw new Exception(name155+ ": Expected exception not thrown: "156+ exceptions.iterator().next());157}158check(sc, state);159log.println(name + ": Returned normally"160+ ((note != null) ? ": " + note : ""));161} finally {162if (sc.isOpen())163sc.close();164}165}166167}168169static void tests() throws Exception {170log.println(remote);171172new Test("Read unconnected", NotYetConnectedException.class,173ST_UNCONNECTED) {174@Override175String go(SocketChannel sc) throws Exception {176ByteBuffer b = ByteBuffer.allocateDirect(1024);177sc.read(b);178return null;179}};180181new Test("Write unconnected", NotYetConnectedException.class,182ST_UNCONNECTED) {183@Override184String go(SocketChannel sc) throws Exception {185ByteBuffer b = ByteBuffer.allocateDirect(1024);186sc.write(b);187return null;188}};189190new Test("Simple connect", NONE, ST_CONNECTED) {191@Override192String go(SocketChannel sc) throws Exception {193sc.connect(remote);194return null;195}};196197new Test("Simple connect & finish", NONE, ST_CONNECTED) {198@Override199String go(SocketChannel sc) throws Exception {200sc.connect(remote);201if (!sc.finishConnect())202throw new Exception("finishConnect returned false");203return null;204}};205206new Test("Double connect",207AlreadyConnectedException.class, ST_CONNECTED) {208@Override209String go(SocketChannel sc) throws Exception {210sc.connect(remote);211sc.connect(remote);212return null;213}};214215new Test("Finish w/o start",216NoConnectionPendingException.class, ST_UNCONNECTED) {217@Override218String go(SocketChannel sc) throws Exception {219sc.finishConnect();220return null;221}};222223// Note: using our local EchoServer rather than echo on a distant224// host - we see that Tries to finish = 0 (instead of ~ 18).225new Test("NB simple connect", NONE, ST_CONNECTED) {226@Override227String go(SocketChannel sc) throws Exception {228sc.configureBlocking(false);229sc.connect(remote);230int n = 0;231while (!sc.finishConnect()) {232Thread.sleep(10);233n++;234}235sc.finishConnect(); // Check redundant invocation236return ("Tries to finish = " + n);237}};238239// Note: using our local EchoServer rather than echo on a distant240// host - we cannot guarantee that this test will get a241// a ConnectionPendingException: it may get an242// AlreadyConnectedException, so we should allow for both.243new Test("NB double connect",244expectedExceptions(ConnectionPendingException.class,245AlreadyConnectedException.class),246ST_PENDING_OR_CONNECTED) {247@Override248String go(SocketChannel sc) throws Exception {249sc.configureBlocking(false);250sc.connect(remote);251sc.connect(remote);252return null;253}};254255new Test("NB finish w/o start",256NoConnectionPendingException.class, ST_UNCONNECTED) {257@Override258String go(SocketChannel sc) throws Exception {259sc.configureBlocking(false);260sc.finishConnect();261return null;262}};263264new Test("NB connect, B finish", NONE, ST_CONNECTED) {265@Override266String go(SocketChannel sc) throws Exception {267sc.configureBlocking(false);268sc.connect(remote);269sc.configureBlocking(true);270sc.finishConnect();271return null;272}};273274}275276public static void main(String[] args) throws Exception {277try (TestServers.EchoServer echoServer278= TestServers.EchoServer.startNewServer(500)) {279remote = new InetSocketAddress(echoServer.getAddress(),280echoServer.getPort());281tests();282}283}284285}286287288