You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/04/07 11:07:38 UTC

svn commit: r392225 [5/6] - in /incubator/harmony/enhanced/classlib/trunk/modules/nio: make/common/ src/main/java/java/nio/ src/main/java/java/nio/channels/spi/ src/main/java/org/apache/harmony/nio/internal/ src/test/java/org/apache/harmony/tests/java/...

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/SocketChannelTest.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/SocketChannelTest.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/SocketChannelTest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/SocketChannelTest.java Fri Apr  7 02:07:34 2006
@@ -0,0 +1,2778 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.BindException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * test for SocketChannel
+ */
+public class SocketChannelTest extends TestCase {
+
+    private static final int capacityNormal = 200;
+
+    private static final int capacity64KB = 65536;
+
+    private InetSocketAddress localAddr1;
+
+    private InetSocketAddress localAddr2;
+
+    private SocketChannel channel1;
+
+    private SocketChannel channel2;
+
+    private ServerSocket server1;
+
+    private ServerSocket server2;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.localAddr1 = new InetSocketAddress("127.0.0.1",
+                Support_PortManager.getNextPort());
+        this.localAddr2 = new InetSocketAddress("127.0.0.1",
+                Support_PortManager.getNextPort());
+        this.channel1 = SocketChannel.open();
+        this.channel2 = SocketChannel.open();
+        this.server1 = new ServerSocket(localAddr1.getPort());
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (null != this.channel1) {
+            this.channel1.close();
+        }
+        if (null != this.channel2) {
+            this.channel2.close();
+        }
+        if (null != this.server1) {
+            this.server1.close();
+        }
+        if (null != this.server2) {
+            this.server2.close();
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for methods in abstract class.
+    // -------------------------------------------------------------------
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.validOps()'
+     */
+    public void testValidOps() {
+        MockSocketChannel testMSChannel = new MockSocketChannel(null);
+        assertEquals(13, this.channel1.validOps());
+        assertEquals(13, testMSChannel.validOps());
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.open()'
+     */
+    public void testOpen() throws IOException {
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+        buf[0] = java.nio.ByteBuffer.allocateDirect(capacityNormal);
+        MockSocketChannel testMSChannel = new MockSocketChannel(null);
+        MockSocketChannel testMSChannelnotnull = new MockSocketChannel(
+                SelectorProvider.provider());
+        assertNull(testMSChannel.provider());
+        assertNotNull(testMSChannelnotnull.provider());
+        assertNotNull(this.channel1);
+        assertEquals(this.channel1.provider(), testMSChannelnotnull.provider());
+        try {
+            this.channel1.write(buf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.open(SocketAddress)'
+     */
+    public void testOpenSocketAddress_Null() throws IOException {
+        SocketChannel channel1IP = null;
+        try {
+            channel1IP = SocketChannel.open(null);
+            fail("Should throw IAE");
+        } catch (IllegalArgumentException e) {
+            // correct
+        }
+        assertNull(channel1IP);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+     */
+    public void testReadByteBufferArray() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        ServerSocket testServer = new ServerSocket(1081);
+        try {
+            this.channel1.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        byteBuf = new java.nio.ByteBuffer[capacityNormal];
+        try {
+            this.channel1.read(byteBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        long readNum = capacityNormal;
+        try {
+            readNum = testMSChannel.read(byteBuf);
+        } catch (NotYetConnectedException e) {
+            fail(e.getMessage());
+        }
+        assertEquals(0, readNum);
+        readNum = capacityNormal;
+        try {
+            readNum = testMSChannelnull.read(byteBuf);
+        } catch (NotYetConnectedException e) {
+            fail(e.getMessage());
+        }
+        assertEquals(0, readNum);
+
+        testServer.close();
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+     */
+    public void testReadByteBufferArray_BufNull() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        byteBuf = null;
+        try {
+            this.channel1.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        long readNum = capacityNormal;
+        try {
+            readNum = testMSChannel.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(capacityNormal, readNum);
+        readNum = capacityNormal;
+        try {
+            readNum = testMSChannelnull.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(capacityNormal, readNum);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+     */
+    public void testWriteByteBufferArray() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        byteBuf = new java.nio.ByteBuffer[capacityNormal];
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        long writeNum = capacityNormal;
+        try {
+            writeNum = testMSChannel.write(byteBuf);
+        } catch (NotYetConnectedException e) {
+            fail(e.getMessage());
+        }
+        assertEquals(0, writeNum);
+        writeNum = capacityNormal;
+        try {
+            writeNum = testMSChannelnull.write(byteBuf);
+        } catch (NotYetConnectedException e) {
+            fail(e.getMessage());
+        }
+        assertEquals(0, writeNum);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+     */
+    public void testWriteByteBufferArray_BufNull() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        long writeNum = capacityNormal;
+        try {
+            writeNum = testMSChannel.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(capacityNormal, writeNum);
+        writeNum = capacityNormal;
+        try {
+            writeNum = testMSChannelnull.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(capacityNormal, writeNum);
+    }
+
+    public void testSocket_BasicStatusBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        Socket s1 = this.channel1.socket();
+        assertSocketBeforeConnect(s1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        assertTrue(this.channel1.connect(localAddr1));
+
+        assertTrue(this.channel1.isConnected());
+        Socket s1 = this.channel1.socket();
+
+        assertSocketAfterConnect(s1, localAddr1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_NonBlock_BasicStatusAfterConnect() throws Exception {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        Socket s1 = this.channel1.socket();
+        // status of not conneted
+        assertSocketBeforeConnect(s1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+
+        if (tryFinish()) {
+            assertTrue(this.channel1.isConnected());
+            s1 = this.channel1.socket();
+            assertSocketAfterConnect(s1, localAddr1);
+            s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+    }
+
+    public void testSocket_Block_ActionsBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        Socket s = this.channel1.socket();
+        assertSocketAction_Block_BeforeConnect(s);
+    }
+
+    public void testSocket_NonBlock_ActionsBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        Socket s = this.channel1.socket();
+        assertSocketAction_NonBlock_BeforeConnect(s);
+    }
+
+    public void testSocket_Block_ActionsAfterConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        assertTrue(this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.isConnected());
+        Socket s = this.channel1.socket();
+        assertSocketAction_Block_AfterConnect(s);
+
+    }
+
+    public void testSocket_NonBlock_ActionsAfterConnectBeforeFinish()
+            throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        Socket s1 = this.channel1.socket();
+        // Action of not conneted
+        assertSocketAction_NonBlock_BeforeConnect(s1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_NonBlock_ActionsAfterConnectAfterFinish()
+            throws Exception {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        if (tryFinish()) {
+            Socket s1 = this.channel1.socket();
+            assertSocketAction_NonBlock_AfterConnect(s1);
+            Socket s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+    }
+
+    private void assertSocketBeforeConnect(Socket s) throws IOException {
+        assertFalse(s.isBound());
+        assertFalse(s.isClosed());
+        assertFalse(s.isConnected());
+        assertFalse(s.getKeepAlive());
+        try {
+            s.getInputStream();
+            fail("Should throw SocketException.");
+        } catch (SocketException e) {
+            // OK.
+        }
+        assertFalse(s.getOOBInline());
+        try {
+            s.getOutputStream();
+            fail("Should throw SocketException.");
+        } catch (SocketException e) {
+            // OK.
+        }
+        assertEquals(-1, s.getSoLinger());
+        assertFalse(s.getTcpNoDelay());
+
+        assertFalse(s.isInputShutdown());
+        assertFalse(s.isOutputShutdown());
+
+        assertNull(s.getInetAddress());
+        assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+        // FIXME ?? -1 means not yet bound. this maybe a bug of RI
+        // RI can't pass this, it returns 0.
+        // assertEquals(s.getLocalPort(), -1);
+        assertNull(s.getLocalSocketAddress());
+
+        // not connected
+        assertEquals(s.getPort(), 0);
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        assertNull(s.getRemoteSocketAddress());
+        // assertFalse(s.getReuseAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(s.getSoTimeout(), 0);
+        assertEquals(s.getTrafficClass(), 0);
+
+    }
+
+    private void assertSocketAfterConnect(Socket s, InetSocketAddress address)
+            throws IOException {
+        assertTrue(s.isBound());
+        assertFalse(s.isClosed());
+        assertTrue(s.isConnected());
+        assertFalse(s.getKeepAlive());
+
+        assertNotNull(s.getInputStream());
+        assertNotNull(s.getOutputStream());
+
+        assertFalse(s.getOOBInline());
+        assertEquals(-1, s.getSoLinger());
+        assertFalse(s.getTcpNoDelay());
+
+        assertFalse(s.isInputShutdown());
+        assertFalse(s.isOutputShutdown());
+
+        assertSame(s.getInetAddress(), address.getAddress());
+
+        assertEquals(s.getLocalAddress(), this.localAddr1.getAddress());
+        assertEquals(s.getPort(), address.getPort());
+        assertNotNull(s.getLocalSocketAddress());
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        // equal , not same
+        assertNotSame(s.getRemoteSocketAddress(), (SocketAddress) address);
+        assertEquals(s.getRemoteSocketAddress(), (SocketAddress) address);
+        // assertFalse(s.getReuseAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(s.getSoTimeout(), 0);
+        assertEquals(s.getTrafficClass(), 0);
+    }
+
+    private void assertSocketAction_Block_BeforeConnect(Socket s)
+            throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        s.connect(localAddr2);
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+
+        assertSocketAfterConnect(s, localAddr2);
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_NonBlock_BeforeConnect(Socket s)
+            throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        try {
+            s.connect(localAddr2);
+            fail("Should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e1) {
+            // OK.
+        }
+
+        if (this.channel1.isConnectionPending()) {
+            try {
+                s.bind(localAddr2);
+                fail("Should throw BindException");
+            } catch (ConnectionPendingException e1) {
+                // OK.
+            }
+        } else {
+            try {
+                s.bind(localAddr2);
+                fail("Should throw BindException");
+            } catch (BindException e1) {
+                // OK.
+            }
+        }
+
+        assertFalse(this.channel1.isConnected());
+        assertFalse(s.isConnected());
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_Block_AfterConnect(Socket s)
+            throws IOException {
+        assertEquals(s.getPort(), localAddr1.getPort());
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+        try {
+            s.connect(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_NonBlock_AfterConnect(Socket s)
+            throws IOException {
+        assertEquals(s.getPort(), localAddr1.getPort());
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+
+        if (this.channel1.isConnectionPending()) {
+            try {
+                s.connect(localAddr2);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // OK.
+            }
+        } else {
+            try {
+                s.connect(localAddr2);
+                fail("Should throw IllegalBlockingModeException");
+            } catch (IllegalBlockingModeException e) {
+                // OK.
+            }
+        }
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    // -------------------------------------------------------------------
+    // Tests for connect(), finishConnect(),isConnected(),isConnectionPending()
+    // These methods are very close, so we test them together, call them "CFII".
+    // -------------------------------------------------------------------
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_NoServer_NonBlock() throws Exception {
+        connectNoServerNonBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_Server_Block() throws Exception {
+        connectServerBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->server closed-->finish-->close
+     */
+    public void testCFII_ServerClosed_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        ensureServerClosed();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->server closed-->finish-->close
+     */
+    public void testCFII_ServerClosed_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        ensureServerClosed();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->server closed-->close
+     */
+    public void testCFII_ServerClosedAfterFinish_Block() throws Exception {
+        connectServerBlock();
+
+        ensureServerClosed();
+        assertTrue(this.channel1.isOpen());
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->server closed-->close
+     */
+    public void testCFII_ServerClosedAfterFinish_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        ensureServerClosed();
+        assertTrue(this.channel1.isOpen());
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * no server-->connect-->server open-->finish-->close
+     */
+    public void testCFII_ServerStartLater_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        ensureServerOpen();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * no server-->connect-->server open-->finish-->close
+     */
+    public void testCFII_ServerStartLater_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        ensureServerOpen();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+
+            this.channel1.close();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_Server_Block() throws Exception {
+        connectServerBlock();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_NoServer_NonBlock()
+            throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+
+        if (this.channel1.isOpen()) {
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect another addr
+            try {
+                this.channel1.connect(localAddr2);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect if server closed
+            ensureServerClosed();
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            this.channel1.close();
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_Server_Block() throws Exception {
+        connectServerBlock();
+
+        if (!this.channel1.isConnected()) {
+            // FIXME: err output for net fail, used in debug time.
+            // System.err
+            // .println("Connection fail,
+            // testCFII_ConnectAfterFinish_Server_Block is not finished.");
+            return;
+        }
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        if (!this.channel1.isConnected()) {
+            System.err
+                    .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+            return;
+        }
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException or a ConnectionPendingException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_Server_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_Server_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_Server_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_Server_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    public void testCFII_Null() throws Exception {
+        statusNotConnected_NotPending();
+        try {
+            this.channel1.connect(null);
+            fail("Should throw a IAE here.");
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_UnsupportedType() throws Exception {
+        class SubSocketAddress extends SocketAddress {
+            /**
+             * Empty
+             */
+            public SubSocketAddress() {
+                super();
+            }
+        }
+        statusNotConnected_NotPending();
+        SocketAddress newTypeAddress = new SubSocketAddress();
+        try {
+            this.channel1.connect(newTypeAddress);
+            fail("Should throw a UnsupportedAddressTypeException here.");
+        } catch (UnsupportedAddressTypeException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_Unresolved() throws IOException {
+        statusNotConnected_NotPending();
+        InetSocketAddress unresolved = new InetSocketAddress(
+                "unresolved address", 1080);
+        try {
+            this.channel1.connect(unresolved);
+            fail("Should throw a UnresolvedAddressException here.");
+        } catch (UnresolvedAddressException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_EmptyHost() throws Exception {
+        statusNotConnected_NotPending();
+        try {
+            this.channel1.connect(new InetSocketAddress("", 1081));
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+    }
+
+    public void testCFII_CloseFirst() throws Exception {
+        this.channel1.close();
+        statusChannelClosed();
+        ensureServerOpen();
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.configureBlocking(false);
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    public void testCFII_StatusAfterFinish() throws Exception {
+        // 1. close server, finish must return false, check the status
+        ensureServerClosed();
+
+        // 1.1 block mode
+        assertTrue(this.channel1.isBlocking());
+        try {
+            assertFalse(this.channel1.connect(localAddr1));
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        assertFalse(this.channel1.isOpen());
+
+        assertFalse(this.channel1.isOpen());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnectionPending());
+
+        // 1.2 non block mode
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            System.out.println(e.getMessage());
+        }
+
+        // 2. start server, finish usually return true, check the status
+        ensureServerOpen();
+
+        // 2.1 block mode
+        this.channel1 = SocketChannel.open();
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.finishConnect());
+        statusConnected_NotPending();
+        this.channel1.close();
+
+        // 2.2 non block mode
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        tryFinish();
+        this.channel1.close();
+    }
+
+    // /////////
+
+    private void ensureServerClosed() throws IOException {
+        if (null != this.server1) {
+            this.server1.close();
+            assertTrue(this.server1.isClosed());
+        }
+        if (null != this.server2) {
+            this.server2.close();
+            assertTrue(this.server2.isClosed());
+        }
+    }
+
+    private void ensureServerOpen() throws IOException {
+        ensureServerClosed();
+        this.server1 = new ServerSocket(localAddr1.getPort());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        assertTrue(this.server1.isBound());
+        assertTrue(this.server2.isBound());
+    }
+
+    private void connectNoServerNonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+        } catch (ConnectException e) {
+            assertEquals(e.getMessage(), "Connection refused");
+        }
+    }
+
+    private void connectServerNonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        tryFinish();
+    }
+
+    private void connectServerBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+        tryFinish();
+    }
+
+    private void statusChannelClosed() {
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void statusNotConnected_NotPending() {
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private void statusNotConnected_Pending() {
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private void statusConnected_NotPending() {
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private boolean tryFinish() throws IOException {
+        /*
+         * the result of finish will be asserted in multi-thread tests.
+         */
+        boolean connected = false;
+        assertTrue(this.channel1.isOpen());
+        try {
+            connected = this.channel1.finishConnect();
+        } catch (SocketException e) {
+            // FIXME
+            // assertTrue(e.getMessage().indexOf("reset")!=-1);
+        }
+        if (connected) {
+            statusConnected_NotPending();
+        }
+        return connected;
+    }
+
+    // ////////////////////////////////////////////////////////////
+
+    // -------------------------------------------------------------------
+    // Original tests. Test method for CFII with real data.
+    // -------------------------------------------------------------------
+
+    /**
+     * 
+     * 'SocketChannelImpl.connect(SocketAddress)'
+     */
+    public void testCFII_Data_ConnectWithServer() throws Exception {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+
+        this.channel1.connect(localAddr1);
+
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(capacityNormal, this.channel1.write(writeBuf));
+        assertEquals(capacityNormal, this.channel1.write(writeBufArr, 0, 1));
+
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // correct
+        }
+
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    /*
+     * Test method for 'SocketChannelImpl.connect(SocketAddress)'
+     */
+    public void testCFII_Data_ConnectWithServer_nonBlocking() throws Exception {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+
+        assertFalse(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        if (tryFinish()) {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            assertEquals(capacityNormal, this.channel1.write(writeBufArr, 0, 1));
+
+            this.channel1.configureBlocking(false);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    /*
+     * Test method for 'SocketChannelImpl.finishConnect()'
+     */
+    public void testCFII_Data_FinishConnect_nonBlocking() throws IOException {
+        ensureServerOpen();
+
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        this.server1.accept();
+        if (tryFinish()) {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            assertEquals(capacityNormal, this.channel1.write(writeBufArr, 0, 1));
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    public void testCFII_Data_FinishConnect_AddrSetServerStartLater()
+            throws IOException, InterruptedException {
+        ensureServerClosed();
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1 = SocketChannel.open(localAddr1);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+        assertTrue(this.channel1.isOpen());
+        assertFalse(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+
+        assertTrue(this.channel1.isBlocking());
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+        assertFalse(this.channel1.isConnected());
+        // finish after finish OK
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isConnected());
+        ensureServerOpen();
+        // cannot connect?
+        try {
+            assertFalse(this.channel1.finishConnect());
+            assertFalse(this.channel1.isBlocking());
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            this.channel1.configureBlocking(true);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            tryFinish();
+        } catch (ConnectException e) {
+            System.out.println(e.getMessage());
+        }
+
+    }
+
+    public void testCFII_Data_FinishConnect_ServerStartLater()
+            throws IOException {
+        ensureServerClosed();
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+        assertFalse(this.channel1.isConnected());
+        // finish after finish OK
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isConnected());
+        ensureServerOpen();
+        // cannot connect?
+        try {
+            assertFalse(this.channel1.finishConnect());
+            assertFalse(this.channel1.isBlocking());
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            this.channel1.configureBlocking(true);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            tryFinish();
+        } catch (ConnectException e) {
+            System.out.println(e.getMessage());
+        }
+    }
+
+    public void testCFII_Data_FinishConnect_Blocking() throws IOException {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+
+        this.channel1.connect(localAddr1);
+
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        if (tryFinish()) {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            assertEquals(capacityNormal, this.channel1.write(writeBufArr, 0, 1));
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    // -------------------------------------------------------------------
+    // End of original tests. Test method for CFII with real data.
+    // -------------------------------------------------------------------
+
+//    public void testCFII_Security() throws Exception {
+//        SocketAddress badAddr = new InetSocketAddress("xxx.com", 2222);
+//        final SecurityManager sm = System.getSecurityManager();
+//        class mySecurityManager extends SecurityManager {
+//            public void checkPermission(Permission perm) {
+//                if (perm.getName().equals("setSecurityManager")) {
+//                    return;
+//                }
+//                super.checkPermission(perm);
+//            }
+//
+//            public void checkConnect(String host, int port) {
+//                // our local addr is OK.
+//                if ("127.0.0.1".equals(host)) {
+//                    return;
+//                }
+//                super.checkConnect(host, port);
+//            }
+//        }
+//        System.setSecurityManager(new mySecurityManager());
+//        // no problem.
+//        this.channel1.connect(localAddr1);
+//        // re open
+//        this.channel1.close();
+//        this.channel1 = SocketChannel.open();
+//        try {
+//            this.channel1.connect(badAddr);
+//            fail("Should throw SecurityException");
+//        } catch (SecurityException ex) {
+//            // OK.
+//        } finally {
+//            System.setSecurityManager(sm);
+//        }
+//    }
+
+    public void testConnect_Lock() throws Exception {
+        final Socket sock = new Socket();
+        new Thread() {
+            public void run() {
+                try {
+                    sock.connect(localAddr2);
+                } catch (Exception e) {
+                    System.out.println("in thread1" + e.getMessage());
+                }
+                if (!sock.isClosed())
+                    System.out.println("T1 not closed");
+            }
+        }.start();
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(200);
+                    sock.connect(localAddr1);
+                } catch (Exception e) {
+                    System.out.println("in thread2" + e.getMessage());
+                }
+                if (!sock.isClosed())
+                    System.out.println("T2 not closed");
+            }
+        }.start();
+        Thread.sleep(2000);
+        sock.close();
+    }
+
+    // -------------------------------------------------
+    // Test for read/write but no real data expressed
+    // -------------------------------------------------
+
+    public void testReadByteBuffer() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            assertEquals(capacityNormal, this.channel1.read(readBuf));
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(readBuf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+
+    }
+
+    public void testReadByteBuffer_BufNull() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(0);
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            assertEquals(capacityNormal, this.channel1
+                    .read((java.nio.ByteBuffer) null));
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        if (tryFinish()) {
+            try {
+                assertEquals(capacityNormal, this.channel1
+                        .read((java.nio.ByteBuffer) null));
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+        this.server1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1
+                    .read((java.nio.ByteBuffer) null));
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer[], int, int)'
+     */
+    public void testReadByteBufferArrayIntInt() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        readBuf[1] = java.nio.ByteBuffer.allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            assertEquals(capacityNormal, this.channel1.read(readBuf, 0, 1));
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+            assertEquals(0, this.channel1.read(readBuf, 0, 2));
+        }
+
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(readBuf, 0, 1));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testReadByteBufferArrayIntInt_BufNull() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            assertEquals(capacityNormal, this.channel1.read(null, 0, 0));
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        if (tryFinish()) {
+
+            try {
+                assertEquals(capacityNormal, this.channel1.read(null, 0, 0));
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+            try {
+                assertEquals(0, this.channel1.read(readBuf, 0, 2));
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(null, 0, 1));
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    } 
+    
+    public void testWriteByteBuffer() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(capacityNormal, this.channel1.write(writeBuf));
+
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+//	  FIXME: unstable test
+//    public void testWriteByteBuffer_afterServerClosed() throws IOException {
+//
+//        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+//                .allocate(capacityNormal);
+//
+//        this.channel1.connect(localAddr1);
+//        this.server1.close();
+//
+//        try {
+//            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+//            fail("Should throw IOException");
+//        } catch (IOException e) {
+//            // correct
+//        }
+//        this.channel1.close();
+//    }
+
+    public void testWriteByteBuffer_BufNull() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer.allocate(0);
+        this.channel1.connect(localAddr1);
+        assertEquals(this.channel1.write(writeBuf), 0);
+        try {
+            this.channel1.write((java.nio.ByteBuffer) null);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.write(ByteBuffer[], int, int)'
+     */
+    public void testWriteByteBufferArrayIntInt() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+        writeBuf[0] = java.nio.ByteBuffer.allocate(capacityNormal);
+        writeBuf[1] = java.nio.ByteBuffer.allocate(capacityNormal);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf, 0, 1));
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(capacityNormal, this.channel1.write(writeBuf, 0, 1));
+        // still writes the same size as above
+        assertEquals(capacityNormal, this.channel1.write(writeBuf, 0, 2));
+        writeBuf[0].flip();
+        writeBuf[1].flip();
+        assertEquals(capacityNormal * 2, this.channel1.write(writeBuf, 0, 2));
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.write(writeBuf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_BufNull() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+        this.channel1.connect(localAddr1);
+        try {
+            this.channel1.write(null, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+        try {
+            this.channel1.write(writeBuf, 0, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        writeBuf = new java.nio.ByteBuffer[1];
+        try {
+            this.channel1.write(writeBuf, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 0, 2);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        this.server1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(null, 0, 1));
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_SizeError() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+        this.channel1.connect(localAddr1);
+        try {
+            this.channel1.write(null, -1, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+        try {
+            this.channel1.write(writeBuf, 0, -1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        writeBuf = new java.nio.ByteBuffer[1];
+        try {
+            this.channel1.write(writeBuf, 2, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 2, -1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        this.server1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(null, -1, -1));
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+    }
+
+    public void testReadByteBufferArrayIntInt_SizeError() throws IOException {
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[0];
+
+        this.channel1.connect(localAddr1);
+        try {
+            this.channel1.read(null, -1, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.read(readBuf, 0, 0));
+        try {
+            this.channel1.read(readBuf, 0, -1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        readBuf = new java.nio.ByteBuffer[1];
+        try {
+            this.channel1.read(readBuf, 2, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        try {
+            this.channel1.read(readBuf, 2, -1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        this.server1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(null, -1, -1));
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+    }
+
+    // -------------------------------------------------
+    // Test for read/write wite real data
+    // -------------------------------------------------
+
+    public void testReadByteBuffer_Blocking_ReadWriteRealData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacityNormal];
+        byte[] serverRBuf = new byte[capacityNormal];
+        for (int i = 0; i < serverWBuf.length; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacityNormal);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertTrue(this.channel1.isConnected());
+        OutputStream out = serverSocket.getOutputStream();
+        InputStream in = serverSocket.getInputStream();
+        out.write(serverWBuf);
+        assertEquals(capacityNormal, this.channel1.read(buf));
+        buf.flip();
+        assertEquals(66051, buf.asIntBuffer().get());
+        assertEquals(capacityNormal, this.channel1.write(buf));
+        in.read(serverRBuf);
+        for (int i = 0; i < serverRBuf.length; i++) {
+            assertEquals((byte) i, serverRBuf[i]);
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBuffer_NonBlocking_ReadWriteRealData()
+            throws Exception {
+        byte[] serverWBuf = new byte[capacityNormal];
+        byte[] serverRBuf = new byte[capacityNormal];
+        for (int i = 0; i < serverWBuf.length; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            OutputStream out = serverSocket.getOutputStream();
+            InputStream in = serverSocket.getInputStream();
+            out.write(serverWBuf);
+            int readCount = this.channel1.read(buf);
+            if (readCount != 0) {
+                assertEquals(capacityNormal, readCount);
+                buf.flip();
+                assertEquals(66051, buf.asIntBuffer().get());
+                assertEquals(capacityNormal, this.channel1.write(buf));
+                in.read(serverRBuf);
+                for (int i = 0; i < serverRBuf.length; i++) {
+                    assertEquals((byte) i, serverRBuf[i]);
+                }
+            }
+        }
+
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArray_Blocking_ReadWriteRealData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacityNormal * 2];
+        byte[] serverRBuf = new byte[capacityNormal * 2];
+        for (int i = 0; i < capacityNormal * 2; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(capacityNormal);
+        buf[1] = ByteBuffer.allocate(capacityNormal);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertTrue(this.channel1.isConnected());
+        OutputStream out = serverSocket.getOutputStream();
+        InputStream in = serverSocket.getInputStream();
+        out.write(serverWBuf);
+        assertEquals(capacityNormal * 2, this.channel1.read(buf));
+        buf[0].flip();
+        buf[1].flip();
+        assertEquals(66051, buf[0].asIntBuffer().get());
+        assertEquals(capacityNormal * 2, this.channel1.write(buf));
+        in.read(serverRBuf);
+
+        for (int i = 0; i < serverRBuf.length; i++) {
+            assertEquals((byte) i, serverRBuf[i]);
+        }
+        for (int i = capacityNormal; i < capacityNormal * 2; i++) {
+            assertEquals((byte) i, serverRBuf[i]);
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArray_NonBlocking_ReadWriteRealData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacityNormal * 2];
+        byte[] serverRBuf = new byte[capacityNormal * 2];
+        for (int i = 0; i < capacityNormal * 2; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(capacityNormal);
+        buf[1] = ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+
+        if (tryFinish()) {
+            OutputStream out = serverSocket.getOutputStream();
+            InputStream in = serverSocket.getInputStream();
+            out.write(serverWBuf);
+            long readCount = this.channel1.read(buf);
+            if (0 != readCount) {
+                assertEquals(capacityNormal * 2, readCount);
+
+                buf[0].flip();
+                buf[1].flip();
+                assertEquals(66051, buf[0].asIntBuffer().get());
+                assertEquals(capacityNormal * 2, this.channel1.write(buf));
+                in.read(serverRBuf);
+
+                for (int i = 0; i < serverRBuf.length; i++) {
+                    assertEquals((byte) i, serverRBuf[i]);
+                }
+                for (int i = capacityNormal; i < capacityNormal * 2; i++) {
+                    assertEquals((byte) i, serverRBuf[i]);
+                }
+            } else {
+                System.err
+                        .println("Read fail, testReadByteBufferArray_NonBlocking_ReadWriteRealData is not finished.");
+            }
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArrayIntInt_Blocking_ReadWriteRealData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacityNormal * 2];
+        byte[] serverRBuf = new byte[capacityNormal * 2];
+        for (int i = 0; i < capacityNormal * 2; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(capacityNormal);
+        buf[1] = ByteBuffer.allocate(capacityNormal);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertTrue(this.channel1.isConnected());
+        OutputStream out = serverSocket.getOutputStream();
+        InputStream in = serverSocket.getInputStream();
+        out.write(serverWBuf);
+        assertEquals(capacityNormal, this.channel1.read(buf, 0, 1));
+        assertEquals(capacityNormal, this.channel1.read(buf, 1, 1));
+        buf[0].flip();
+        buf[1].flip();
+        assertEquals(66051, buf[0].asIntBuffer().get());
+        assertEquals(capacityNormal, this.channel1.write(buf, 1, 1));
+        in.read(serverRBuf);
+
+        for (int i = 0; i < capacityNormal; i++) {
+            assertEquals((byte) (i + capacityNormal), serverRBuf[i]);
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArrayIntInt_NonBlocking_ReadWriteRealData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacityNormal * 2];
+        byte[] serverRBuf = new byte[capacityNormal * 2];
+        for (int i = 0; i < capacityNormal * 2; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(capacityNormal);
+        buf[1] = ByteBuffer.allocate(capacityNormal);
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        if (tryFinish()) {
+            OutputStream out = serverSocket.getOutputStream();
+            InputStream in = serverSocket.getInputStream();
+            out.write(serverWBuf);
+            long readCount = this.channel1.read(buf, 0, 1);
+            if (readCount > 0) {
+                assertEquals(capacityNormal, readCount);
+                buf[0].flip();
+                assertEquals(66051, buf[0].asIntBuffer().get());
+                readCount = this.channel1.read(buf, 1, 1);
+                if (readCount > 0) {
+                    assertEquals(capacityNormal, readCount);
+                    buf[1].flip();
+                    assertEquals(capacityNormal, this.channel1.write(buf, 1, 1));
+                    readCount = in.read(serverRBuf);
+                    if (readCount > 0) {
+                        assertEquals(capacityNormal, readCount);
+                        for (int i = 0; i < capacityNormal; i++) {
+                            assertEquals((byte) (i + capacityNormal),
+                                    serverRBuf[i]);
+                        }
+                    } else {
+                        System.err
+                                .println("fail to read buf[1] again, testReadByteBufferArrayIntInt_NonBlocking_ReadWriteRealData not finish.");
+                    }
+                } else {
+                    System.err
+                            .println("fail to read buf[1], testReadByteBufferArrayIntInt_NonBlocking_ReadWriteRealData not finish.");
+                }
+            } else {
+                System.err
+                        .println("fail to read buf[0], testReadByteBufferArrayIntInt_NonBlocking_ReadWriteRealData not finish.");
+            }
+
+        } else {
+            System.err
+                    .println("fail to connect, testReadByteBufferArrayIntInt_NonBlocking_ReadWriteRealData not finish.");
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBuffer_Blocking_ReadWriteRealLargeData()
+            throws IOException {
+        byte[] serverWBuf = new byte[capacity64KB];
+        byte[] serverRBuf = new byte[capacity64KB];
+        for (int i = 0; i < serverWBuf.length; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer buf = java.nio.ByteBuffer
+                .allocateDirect(capacity64KB);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertTrue(this.channel1.isConnected());
+        OutputStream out = serverSocket.getOutputStream();
+        InputStream in = serverSocket.getInputStream();
+        out.write(serverWBuf);
+        int count = 0;
+        int total = 0;
+        while ((count = this.channel1.read(buf)) > 0)
+            total = total + count;
+        if (0 != total) {
+            assertEquals(total, capacity64KB);
+        } else {
+            // FIXME: err output for net fail, used in debug time.
+            // System.err
+            // .println("Read fail,
+            // testReadByteBuffer_Blocking_ReadWriteRealLargeData is not
+            // complete.");
+        }
+        buf.flip();
+        assertEquals(66051, buf.asIntBuffer().get());
+        assertEquals(capacity64KB, this.channel1.write(buf));
+        count = in.read(serverRBuf);
+        for (int i = 0; i < count; i++) {
+            assertEquals((byte) i, serverRBuf[i]);
+        }
+        this.channel1.close();
+        try {
+            assertEquals(capacityNormal, this.channel1.read(buf));
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBuffer_NonBlocking_ReadWriteRealLargeData()
+            throws Exception {
+        byte[] serverWBuf = new byte[capacity64KB];
+        byte[] serverRBuf = new byte[capacity64KB];
+        for (int i = 0; i < serverWBuf.length; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        int writeCount = 0;
+        java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity64KB);
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        Socket serverSocket = this.server1.accept();
+        assertFalse(this.channel1.isConnected());
+        if (tryFinish()) {
+            OutputStream out = serverSocket.getOutputStream();
+            InputStream in = serverSocket.getInputStream();
+            out.write(serverWBuf);
+            int count = 0;
+            int total = 0;
+            while ((count = this.channel1.read(buf)) != 0) {
+                total = total + count;
+            }
+            if (total > 0) {
+                assertEquals(total, capacity64KB);
+                buf.flip();

[... 260 lines stripped ...]