blob: 1da0bcc6f2236a26bedff3ead7d8cb279929770f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.nio.tests.java.nio.channels;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.NotYetBoundException;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import junit.framework.TestCase;
import tests.support.Support_PortManager;
/*
* test for ServerSocketChannel
*/
public class ServerSocketChannelTest extends TestCase {
private static final int CAPACITY_NORMAL = 200;
private static final int CAPACITY_64KB = 65536;
private static final int TIME_UNIT = 200;
private InetSocketAddress localAddr1;
private ServerSocketChannel serverChannel;
private SocketChannel clientChannel;
protected void setUp() throws Exception {
super.setUp();
this.localAddr1 = new InetSocketAddress(
"127.0.0.1", Support_PortManager
.getNextPort());
this.serverChannel = ServerSocketChannel.open();
this.clientChannel = SocketChannel.open();
}
protected void tearDown() throws Exception {
if (null != this.serverChannel) {
try {
this.serverChannel.close();
} catch (Exception e) {
//ignore
}
}
if (null != this.clientChannel) {
try {
this.clientChannel.close();
} catch (Exception e) {
//ignore
}
}
super.tearDown();
}
// -------------------------------------------------------------------
// Test for methods in abstract class.
// -------------------------------------------------------------------
/*
* Test method for 'java.nio.channels.ServerSocketChannel.validOps()'
*/
public void testValidOps() {
MockServerSocketChannel testMSChnlnull = new MockServerSocketChannel(
null);
MockServerSocketChannel testMSChnl = new MockServerSocketChannel(
SelectorProvider.provider());
assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
assertEquals(SelectionKey.OP_ACCEPT, testMSChnl.validOps());
assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnull.validOps());
}
/*
* Test method for 'java.nio.channels.ServerSocketChannel.open()'
*/
public void testOpen() {
MockServerSocketChannel testMSChnl = new MockServerSocketChannel(null);
MockServerSocketChannel testMSChnlnotnull = new MockServerSocketChannel(
SelectorProvider.provider());
assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnotnull.validOps());
assertNull(testMSChnl.provider());
assertNotNull(testMSChnlnotnull.provider());
assertNotNull(this.serverChannel.provider());
assertEquals(testMSChnlnotnull.provider(), this.serverChannel
.provider());
}
// -------------------------------------------------------------------
// Test for socket()
// -------------------------------------------------------------------
/*
* Test method for 'com.ibm.io.nio.ServerSocketChannelImpl.socket()'
*/
public void testSocket_Block_BeforeClose() throws Exception {
assertTrue(this.serverChannel.isOpen());
assertTrue(this.serverChannel.isBlocking());
ServerSocket s1 = this.serverChannel.socket();
assertFalse(s1.isClosed());
assertSocketNotAccepted(s1);
ServerSocket s2 = this.serverChannel.socket();
// same
assertSame(s1, s2);
// socket close makes the channel close
s1.close();
assertFalse(this.serverChannel.isOpen());
}
public void testSocket_NonBlock_BeforeClose() throws Exception {
assertTrue(this.serverChannel.isOpen());
this.serverChannel.configureBlocking(false);
ServerSocket s1 = this.serverChannel.socket();
assertFalse(s1.isClosed());
assertSocketNotAccepted(s1);
ServerSocket s2 = this.serverChannel.socket();
// same
assertSame(s1, s2);
// socket close makes the channel close
s1.close();
assertFalse(this.serverChannel.isOpen());
}
public void testSocket_Block_Closed() throws Exception {
this.serverChannel.close();
assertFalse(this.serverChannel.isOpen());
assertTrue(this.serverChannel.isBlocking());
ServerSocket s1 = this.serverChannel.socket();
assertTrue(s1.isClosed());
assertSocketNotAccepted(s1);
ServerSocket s2 = this.serverChannel.socket();
// same
assertSame(s1, s2);
}
public void testSocket_NonBlock_Closed() throws Exception {
this.serverChannel.configureBlocking(false);
this.serverChannel.close();
assertFalse(this.serverChannel.isBlocking());
assertFalse(this.serverChannel.isOpen());
ServerSocket s1 = this.serverChannel.socket();
assertTrue(s1.isClosed());
assertSocketNotAccepted(s1);
ServerSocket s2 = this.serverChannel.socket();
// same
assertSame(s1, s2);
}
private void assertSocketNotAccepted(ServerSocket s) throws IOException {
assertFalse(s.isBound());
assertNull(s.getInetAddress());
assertEquals(-1, s.getLocalPort());
assertNull(s.getLocalSocketAddress());
assertEquals(0, s.getSoTimeout());
}
public void testChannelBasicStatus() {
ServerSocket gotSocket = this.serverChannel.socket();
assertFalse(gotSocket.isClosed());
assertTrue(this.serverChannel.isBlocking());
assertFalse(this.serverChannel.isRegistered());
assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
assertEquals(SelectorProvider.provider(), this.serverChannel.provider());
}
// -------------------------------------------------------------------
// Test for accept()
// -------------------------------------------------------------------
/*
* Test method for 'com.ibm.io.nio.ServerSocketChannelImpl.accept()'
*/
public void testAccept_Block_NotYetBound() throws IOException {
assertTrue(this.serverChannel.isOpen());
assertTrue(this.serverChannel.isBlocking());
try {
this.serverChannel.accept();
fail("Should throw NotYetBoundException");
} catch (NotYetBoundException e) {
// correct
}
}
public void testAccept_NonBlock_NotYetBound() throws IOException {
assertTrue(this.serverChannel.isOpen());
this.serverChannel.configureBlocking(false);
try {
this.serverChannel.accept();
fail("Should throw NotYetBoundException");
} catch (NotYetBoundException e) {
// correct
}
}
public void testAccept_ClosedChannel() throws Exception {
this.serverChannel.close();
assertFalse(this.serverChannel.isOpen());
try {
this.serverChannel.accept();
fail("Should throw ClosedChannelException");
} catch (ClosedChannelException e) {
// OK.
}
}
public void testAccept_Block_NoConnect() throws IOException {
assertTrue(this.serverChannel.isBlocking());
ServerSocket gotSocket = this.serverChannel.socket();
gotSocket.bind(localAddr1);
// blocking mode , will block and wait for ever...
// so must close the server channel with another thread.
new Thread() {
public void run() {
try {
Thread.sleep(TIME_UNIT);
ServerSocketChannelTest.this.serverChannel.close();
} catch (Exception e) {
fail("Fail to close the server channel because of"
+ e.getClass().getName());
}
}
}.start();
try {
this.serverChannel.accept();
fail("Should throw a AsynchronousCloseException");
} catch (AsynchronousCloseException e) {
// OK.
}
}
public void testAccept_NonBlock_NoConnect() throws IOException {
ServerSocket gotSocket = this.serverChannel.socket();
gotSocket.bind(localAddr1);
this.serverChannel.configureBlocking(false);
// non-blocking mode , will immediately return
assertNull(this.serverChannel.accept());
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_read_Blocking_RealData() throws IOException {
serverChannel.socket().bind(localAddr1);
ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
for (int i = 0; i < CAPACITY_NORMAL; i++) {
buf.put((byte) i);
}
clientChannel.connect(localAddr1);
Socket serverSocket = serverChannel.accept().socket();
InputStream in = serverSocket.getInputStream();
buf.flip();
clientChannel.write(buf);
clientChannel.close();
assertReadResult(in,CAPACITY_NORMAL);
}
/**
* Asserts read content. The read content should contain <code>size</code>
* bytes, and the value should be a sequence from 0 to size-1
* ([0,1,...size-1]). Otherwise, the method throws Exception.
*
*/
private void assertReadResult(InputStream in, int size) throws IOException{
byte[] readContent = new byte[size + 1];
int count = 0;
int total = 0;
while ((count = in.read(readContent, total, size + 1 - total)) != -1) {
total = total + count;
}
assertEquals(size, total);
for (int i = 0; i < size; i++) {
assertEquals((byte) i, readContent[i]);
}
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_read_NonBlocking_RealData() throws Exception {
serverChannel.configureBlocking(false);
serverChannel.socket().bind(localAddr1);
ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
for (int i = 0; i < CAPACITY_NORMAL; i++) {
buf.put((byte) i);
}
buf.flip();
clientChannel.connect(localAddr1);
Socket serverSocket = serverChannel.accept().socket();
InputStream in = serverSocket.getInputStream();
clientChannel.write(buf);
clientChannel.close();
assertReadResult(in,CAPACITY_NORMAL);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_write_Blocking_RealData() throws IOException {
assertTrue(serverChannel.isBlocking());
ServerSocket serverSocket = serverChannel.socket();
serverSocket.bind(localAddr1);
byte[] writeContent = new byte[CAPACITY_NORMAL];
for (int i = 0; i < writeContent.length; i++) {
writeContent[i] = (byte) i;
}
clientChannel.connect(localAddr1);
Socket socket = serverChannel.accept().socket();
OutputStream out = socket.getOutputStream();
out.write(writeContent);
out.flush();
socket.close();
assertWriteResult(CAPACITY_NORMAL);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_write_NonBlocking_RealData() throws Exception {
serverChannel.configureBlocking(false);
ServerSocket serverSocket = serverChannel.socket();
serverSocket.bind(localAddr1);
byte[] writeContent = new byte[CAPACITY_NORMAL];
for (int i = 0; i < CAPACITY_NORMAL; i++) {
writeContent[i] = (byte) i;
}
clientChannel.connect(localAddr1);
Socket clientSocket = serverChannel.accept().socket();
OutputStream out = clientSocket.getOutputStream();
out.write(writeContent);
clientSocket.close();
assertWriteResult(CAPACITY_NORMAL);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_read_LByteBuffer_Blocking_ReadWriteRealLargeData()
throws IOException {
serverChannel.socket().bind(localAddr1);
ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
for (int i = 0; i < CAPACITY_64KB; i++) {
buf.put((byte) i);
}
buf.flip();
clientChannel.connect(localAddr1);
clientChannel.write(buf);
clientChannel.close();
Socket socket = serverChannel.accept().socket();
InputStream in = socket.getInputStream();
assertReadResult(in,CAPACITY_64KB);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_read_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
throws Exception {
serverChannel.configureBlocking(false);
serverChannel.socket().bind(localAddr1);
ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
for (int i = 0; i < CAPACITY_64KB; i++) {
buf.put((byte) i);
}
buf.flip();
clientChannel.connect(localAddr1);
clientChannel.write(buf);
clientChannel.close();
Socket socket = serverChannel.accept().socket();
InputStream in = socket.getInputStream();
assertReadResult(in,CAPACITY_64KB);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_write_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
throws Exception {
serverChannel.configureBlocking(false);
serverChannel.socket().bind(localAddr1);
byte[] writeContent = new byte[CAPACITY_64KB];
for (int i = 0; i < writeContent.length; i++) {
writeContent[i] = (byte) i;
}
clientChannel.connect(localAddr1);
Socket socket = serverChannel.accept().socket();
OutputStream out = socket.getOutputStream();
out.write(writeContent);
socket.close();
assertWriteResult(CAPACITY_64KB);
}
/**
* @tests ServerSocketChannel#accept().socket()
*/
public void test_write_LByteBuffer_Blocking_ReadWriteRealLargeData()
throws Exception {
serverChannel.socket().bind(localAddr1);
byte[] writeContent = new byte[CAPACITY_64KB];
for (int i = 0; i < writeContent.length; i++) {
writeContent[i] = (byte) i;
}
clientChannel.connect(localAddr1);
Socket socket = serverChannel.accept().socket();
OutputStream out = socket.getOutputStream();
out.write(writeContent);
socket.close();
assertWriteResult(CAPACITY_64KB);
}
/**
* Uses SocketChannel.read(ByteBuffer) to verify write result.
*/
private void assertWriteResult(int size) throws IOException{
ByteBuffer buf = ByteBuffer.allocate(size + 1);
int count = 0;
int total = 0;
long beginTime = System.currentTimeMillis();
while ((count = clientChannel.read(buf)) != -1) {
total = total + count;
// 10s timeout to avoid dead loop
if (System.currentTimeMillis() - beginTime > 10000){
break;
}
}
assertEquals(total, size);
buf.flip();
for (int i = 0; i < count; i++) {
assertEquals((byte) i, buf.get(i));
}
}
/**
* @tests ServerSocketChannel#socket().getSoTimeout()
*/
public void test_accept_SOTIMEOUT() throws IOException {
// regression test for Harmony-707
final int SO_TIMEOUT = 10;
ServerSocketChannel sc = ServerSocketChannel.open();
try {
ServerSocket ss = sc.socket();
ss.bind(localAddr1);
sc.configureBlocking(false);
ss.setSoTimeout(SO_TIMEOUT);
SocketChannel client = sc.accept();
// non blocking mode, returns null since there are no pending connections.
assertNull(client);
int soTimeout = ss.getSoTimeout();
// Harmony fails here.
assertEquals(SO_TIMEOUT, soTimeout);
} finally {
sc.close();
}
}
/**
* @tests ServerSocket#socket().accept()
*/
public void test_socket_accept_Blocking_NotBound() throws IOException {
// regression test for Harmony-748
ServerSocket gotSocket = serverChannel.socket();
serverChannel.configureBlocking(true);
try {
gotSocket.accept();
fail("Should throw an IllegalBlockingModeException");
} catch (IllegalBlockingModeException e) {
// expected
}
serverChannel.close();
try {
gotSocket.accept();
fail("Should throw an IllegalBlockingModeException");
} catch (IllegalBlockingModeException e) {
// expected
}
}
/**
* @tests ServerSocket#socket().accept()
*/
public void test_socket_accept_Nonblocking_NotBound() throws IOException {
// regression test for Harmony-748
ServerSocket gotSocket = serverChannel.socket();
serverChannel.configureBlocking(false);
try {
gotSocket.accept();
fail("Should throw an IllegalBlockingModeException");
} catch (IllegalBlockingModeException e) {
// expected
}
serverChannel.close();
try {
gotSocket.accept();
fail("Should throw an IllegalBlockingModeException");
} catch (IllegalBlockingModeException e) {
// expected
}
}
/**
* @tests ServerSocket#socket().accept()
*/
public void test_socket_accept_Nonblocking_Bound() throws IOException {
// regression test for Harmony-748
serverChannel.configureBlocking(false);
ServerSocket gotSocket = serverChannel.socket();
gotSocket.bind(localAddr1);
try {
gotSocket.accept();
fail("Should throw an IllegalBlockingModeException");
} catch (IllegalBlockingModeException e) {
// expected
}
serverChannel.close();
try {
gotSocket.accept();
fail("Should throw a ClosedChannelException");
} catch (ClosedChannelException e) {
// expected
}
}
/**
* @tests ServerSocket#socket().accept()
*/
public void test_socket_accept_Blocking_Bound() throws IOException {
// regression test for Harmony-748
serverChannel.configureBlocking(true);
ServerSocket gotSocket = serverChannel.socket();
gotSocket.bind(localAddr1);
serverChannel.close();
try {
gotSocket.accept();
fail("Should throw a ClosedChannelException");
} catch (ClosedChannelException e) {
// expected
}
}
/**
* Regression test for HARMONY-4961
*/
public void test_socket_getLocalPort() throws IOException {
serverChannel.socket().bind(localAddr1);
clientChannel.connect(localAddr1);
SocketChannel myChannel = serverChannel.accept();
int port = myChannel.socket().getLocalPort();
assertEquals(localAddr1.getPort(), port);
myChannel.close();
clientChannel.close();
serverChannel.close();
}
}