test/java/nio/channels/SocketChannel/ConnectState.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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.

@@ -28,24 +28,45 @@
 
 import java.io.*;
 import java.net.*;
 import java.nio.*;
 import java.nio.channels.*;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 
 
 public class ConnectState {
 
     static PrintStream log = System.err;
 
-    static String REMOTE_HOST = TestUtil.HOST;
-    static int REMOTE_PORT = 7;                         // echo
     static InetSocketAddress remote;
 
     final static int ST_UNCONNECTED = 0;
     final static int ST_PENDING = 1;
     final static int ST_CONNECTED = 2;
     final static int ST_CLOSED = 3;
+    final static int ST_PENDING_OR_CONNECTED = 4;
+    // NO exceptions expected
+    final static Collection<Class<?>> NONE = Collections.emptySet();
+
+    // make a set of expected exception.
+    // calling expectedExceptions(null) will always return NONE.
+    static Collection<Class<?>> expectedExceptions(Class<?>... expected) {
+        final Collection<Class<?>> exceptions;
+        if (expected == null || expected.length == 0) {
+            exceptions = NONE;
+        } else if (expected.length == 0 && expected[0] == null) {
+            exceptions = NONE;
+        } else if (expected.length == 1) {
+            exceptions = Collections.<Class<?>>singleton(expected[0]);
+        } else {
+            exceptions = new HashSet<>(Arrays.asList(expected));
+        }
+        return exceptions;
+    }
 
     static abstract class Test {
 
         abstract String go(SocketChannel sc) throws Exception;
 

@@ -74,41 +95,67 @@
             case ST_CLOSED:
                 check(sc.isConnected(), "isConnected");
                 check(!sc.isConnectionPending(), "!isConnectionPending");
                 check(sc.isOpen(), "isOpen");
                 break;
+            case ST_PENDING_OR_CONNECTED:
+                check(sc.isConnected() || sc.isConnectionPending(),
+                        "isConnected || isConnectionPending");
+                check(sc.isOpen(), "isOpen");
+                break;
             }
         }
 
-        Test(String name, Class exception, int state) throws Exception {
+        Test(String name, Class<?> exception, int state) throws Exception {
+            this(name, expectedExceptions(exception), state);
+        }
+
+        // On some architecture we may need to accept several exceptions.
+        // For instance on Solaris, when using a server colocated on the 
+        // machine we cannot guarantee that we will get a ConnectionPending
+        // exception when connecting twice on the same non-blocking socket. 
+        // We may get a an AlreadyConnected exception, which is also valid: it 
+        // simply means that the first connection as been immediately accepted.
+        Test(String name, Collection<Class<?>> exceptions, int state) throws Exception {
             SocketChannel sc = SocketChannel.open();
-            String note = null;
+            String note;
             try {
                 try {
                     note = go(sc);
                 } catch (Exception x) {
-                    if (exception != null) {
+                    Class<?> expectedExceptionClass = null;
+                    for (Class<?> exception : exceptions) {
                         if (exception.isInstance(x)) {
                             log.println(name + ": As expected: "
                                         + x);
+                            expectedExceptionClass = exception;
                             check(sc, state);
-                            return;
-                        } else {
+                            break;
+                        }
+                    }
+                    if (expectedExceptionClass == null
+                            && !exceptions.isEmpty()) {
+                        // we had an exception, but it's not of the set of 
+                        // exceptions we expected.
                             throw new Exception(name
                                                 + ": Incorrect exception",
                                                 x);
-                        }
-                    } else {
+                    } else if (exceptions.isEmpty()) {
+                        // we didn't expect any exception
                         throw new Exception(name
                                             + ": Unexpected exception",
                                             x);
                     }
+                    // if we reach here, we have our expected exception
+                    assert expectedExceptionClass != null;
+                    return;
                 }
-                if (exception != null)
+                if (!exceptions.isEmpty()) {
                     throw new Exception(name
                                         + ": Expected exception not thrown: "
-                                        + exception);
+                                        + exceptions.iterator().next());
+                }
                 check(sc, state);
                 log.println(name + ": Returned normally"
                             + ((note != null) ? ": " + note : ""));
             } finally {
                 if (sc.isOpen())

@@ -121,54 +168,63 @@
     static void tests() throws Exception {
         log.println(remote);
 
         new Test("Read unconnected", NotYetConnectedException.class,
                  ST_UNCONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     ByteBuffer b = ByteBuffer.allocateDirect(1024);
                     sc.read(b);
                     return null;
                 }};
 
         new Test("Write unconnected", NotYetConnectedException.class,
                  ST_UNCONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     ByteBuffer b = ByteBuffer.allocateDirect(1024);
                     sc.write(b);
                     return null;
                 }};
 
-        new Test("Simple connect", null, ST_CONNECTED) {
+        new Test("Simple connect", NONE, ST_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.connect(remote);
                     return null;
                 }};
 
-        new Test("Simple connect & finish", null, ST_CONNECTED) {
+        new Test("Simple connect & finish", NONE, ST_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.connect(remote);
                     if (!sc.finishConnect())
                         throw new Exception("finishConnect returned false");
                     return null;
                 }};
 
         new Test("Double connect",
                  AlreadyConnectedException.class, ST_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.connect(remote);
                     sc.connect(remote);
                     return null;
                 }};
 
         new Test("Finish w/o start",
                  NoConnectionPendingException.class, ST_UNCONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.finishConnect();
                     return null;
                 }};
 
-        new Test("NB simple connect", null, ST_CONNECTED) {
+        // Note: using our local EchoServer rather than echo on a distant
+        //       host - we see that Tries to finish = 0 (instead of ~ 18).
+        new Test("NB simple connect", NONE, ST_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.configureBlocking(false);
                     sc.connect(remote);
                     int n = 0;
                     while (!sc.finishConnect()) {

@@ -177,28 +233,38 @@
                     }
                     sc.finishConnect();         // Check redundant invocation
                     return ("Tries to finish = " + n);
                 }};
 
+        // Note: using our local EchoServer rather than echo on a distant
+        //       host - we cannot guarantee that this test will get a
+        //       a ConnectionPendingException: it may get an AlreadyConnectedException,
+        //       so we should allow for both.
         new Test("NB double connect",
-                 ConnectionPendingException.class, ST_PENDING) {
+                    expectedExceptions(
+                        ConnectionPendingException.class,
+                        AlreadyConnectedException.class),
+                    ST_PENDING_OR_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.configureBlocking(false);
                     sc.connect(remote);
                     sc.connect(remote);
                     return null;
                 }};
 
         new Test("NB finish w/o start",
                  NoConnectionPendingException.class, ST_UNCONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.configureBlocking(false);
                     sc.finishConnect();
                     return null;
                 }};
 
-        new Test("NB connect, B finish", null, ST_CONNECTED) {
+        new Test("NB connect, B finish", NONE, ST_CONNECTED) {
+                @Override
                 String go(SocketChannel sc) throws Exception {
                     sc.configureBlocking(false);
                     sc.connect(remote);
                     sc.configureBlocking(true);
                     sc.finishConnect();

@@ -206,11 +272,14 @@
                 }};
 
     }
 
     public static void main(String[] args) throws Exception {
-        remote = new InetSocketAddress(InetAddress.getByName(REMOTE_HOST),
-                                       REMOTE_PORT);
+        try (TestUtil.EchoServer echoServer =
+                        TestUtil.EchoServer.startNewServer(500)) {
+            remote = new InetSocketAddress(echoServer.getAddress(),
+                    echoServer.getPort());
         tests();
     }
+    }
 
 }