blob: d918087ea069d60946fe9812b89200e758bce9a8 [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.camel.test.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.fail;
/**
* Various tests used to validate the behaviour of Java Sockets.
*
* The tests were for experimentation and don't have any assertions in them - JUnit provided a convenient framework to explore this behaviour. These tests shouldn't be run with a normal build since
* they don't have any assertions and don't validate any results.
*
* NOTE: This class may be deleted in the future
*/
@Ignore(value = "Tests validating Java Socket behaviours")
public class JavaSocketTests {
Logger log = LoggerFactory.getLogger(this.getClass());
Socket clientSocket;
ServerSocket serverSocket;
int messageCount = 10;
@Before
public void setUp() throws Exception {
serverSocket = new ServerSocket(0);
}
@After
public void tearDown() throws Exception {
if (null != clientSocket) {
clientSocket.close();
}
if (null != serverSocket) {
serverSocket.close();
}
}
@Test
public void testSocketReadOnClosedConnection() throws Exception {
final Thread acceptThread = new Thread() {
Logger log = LoggerFactory.getLogger("acceptThread");
@Override
public void run() {
try {
Socket echoSocket = serverSocket.accept();
log.info("Accepted connection: {}", echoSocket.getInetAddress());
echoSocket.setSoTimeout(2000);
while (echoSocket.isConnected() && !echoSocket.isClosed()) {
StringBuilder responseBuilder = new StringBuilder(500);
InputStream reader = echoSocket.getInputStream();
OutputStream writer = echoSocket.getOutputStream();
do {
int readByte = -1;
int available = -1;
try {
available = reader.available();
log.info("InputStream.available returned {}", available);
readByte = reader.read();
log.trace("Processing byte: {}", readByte);
switch (readByte) {
case -1:
if (echoSocket.isConnected() && !echoSocket.isClosed()) {
log.info("Available returned {}", reader.available());
log.warn("Socket claims to still be open, but END_OF_STREAM received - closing echoSocket");
try {
echoSocket.close();
} catch (Exception ex) {
log.warn("Exception encountered closing echoSocket after END_OF_STREAM received", ex);
}
}
break;
case 10:
log.info("Complete Message - Sending Response");
byte[] response = responseBuilder.toString().getBytes();
responseBuilder.setLength(0);
writer.write(response, 0, response.length);
writer.write('\n');
break;
default:
responseBuilder.append((char) readByte);
}
} catch (SocketTimeoutException timeoutEx) {
log.info("Timeout reading data - available returned {}", available);
}
} while (echoSocket.isConnected() && !echoSocket.isClosed());
}
} catch (IOException ioEx) {
log.error("IOException in run method", ioEx);
} finally {
try {
serverSocket.close();
} catch (IOException ioEx) {
log.error("Exception encountered closing server socket", ioEx);
}
}
log.info("Finished processing connection");
}
};
acceptThread.start();
clientSocket = new Socket();
clientSocket.setSoTimeout(1000);
clientSocket.connect(serverSocket.getLocalSocketAddress(), 10000);
clientSocket.setTcpNoDelay(true);
log.info("Begining message send loop ");
byte[] message = "Hello World".getBytes();
BufferedReader reader;
for (int i = 1; i <= messageCount; ++i) {
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
OutputStream writer = clientSocket.getOutputStream();
log.info("Sending payload");
writer.write(message, 0, message.length);
writer.flush();
log.info("Sending terminator");
writer.write('\n');
writer.flush();
log.info("Received Response #{}: {}", i, reader.readLine());
Thread.sleep(1000);
}
log.info("Message send loop complete - closing connection");
// Javadoc for Socket says closing the InputStream will close the connection
clientSocket.getInputStream().close();
if (!clientSocket.isClosed()) {
log.warn("Closing input stream didn't close socket");
clientSocket.close();
}
log.info("Sleeping ...");
Thread.sleep(5000);
}
@Test
public void testAvailableOnClosedConnection() throws Exception {
final Thread acceptThread = new Thread() {
Logger log = LoggerFactory.getLogger("acceptThread");
@Override
public void run() {
try {
Socket echoSocket = serverSocket.accept();
log.info("Accepted connection: {}", echoSocket.getInetAddress());
echoSocket.setSoTimeout(2000);
while (echoSocket.isConnected() && !echoSocket.isClosed()) {
StringBuilder responseBuilder = new StringBuilder(500);
InputStream reader = echoSocket.getInputStream();
OutputStream writer = echoSocket.getOutputStream();
do {
int readByte = -1;
int available = -1;
try {
available = reader.available();
log.info("InputStream.available returned {}", available);
readByte = reader.read();
log.trace("Processing byte: {}", readByte);
switch (readByte) {
case -1:
if (echoSocket.isConnected() && !echoSocket.isClosed()) {
log.info("Available returned {}", reader.available());
log.warn("Socket claims to still be open, but END_OF_STREAM received - closing echoSocket");
try {
echoSocket.close();
} catch (Exception ex) {
log.warn("Exception encountered closing echoSocket after END_OF_STREAM received", ex);
}
}
break;
case 27: // Escape
log.info("Received Escape - closing connection");
echoSocket.close();
break;
case 10:
log.info("Complete Message - Sending Response");
byte[] response = responseBuilder.toString().getBytes();
responseBuilder.setLength(0);
writer.write(response, 0, response.length);
writer.write('\n');
break;
default:
responseBuilder.append((char) readByte);
}
} catch (SocketTimeoutException timeoutEx) {
log.info("Timeout reading data - available returned {}", available);
}
} while (echoSocket.isConnected() && !echoSocket.isClosed());
}
} catch (IOException ioEx) {
log.error("IOException in run method", ioEx);
} finally {
try {
serverSocket.close();
} catch (IOException ioEx) {
log.error("Exception encountered closing server socket", ioEx);
}
}
log.info("Finished processing connection");
}
};
acceptThread.start();
clientSocket = new Socket();
clientSocket.setSoTimeout(1000);
clientSocket.connect(serverSocket.getLocalSocketAddress(), 10000);
clientSocket.setTcpNoDelay(true);
log.info("Begining message send loop ");
byte[] message = "Hello World".getBytes();
BufferedReader reader;
for (int i = 1; i <= messageCount; ++i) {
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
OutputStream writer = clientSocket.getOutputStream();
log.info("Sending payload");
writer.write(message, 0, message.length);
writer.flush();
log.info("Sending terminator");
writer.write('\n');
writer.flush();
log.info("Received Response #{}: {}", i, reader.readLine());
Thread.sleep(1000);
}
log.info("Message send loop complete - closing connection");
log.info("Client Socket available() returned {} before close", clientSocket.getInputStream().available());
try {
clientSocket.getInputStream().read();
fail("read should have timed-out");
} catch (SocketTimeoutException timeoutEx) {
log.info("Client Socket read() timed-out before close");
}
clientSocket.getOutputStream().write(27);
Thread.sleep(1000);
log.info("Client Socket available() returned {} after close", clientSocket.getInputStream().available());
log.info("Client Socket read() returned {} after close", clientSocket.getInputStream().read());
// Javadoc for Socket says closing the InputStream will close the connection
clientSocket.getInputStream().close();
if (!clientSocket.isClosed()) {
log.warn("Closing input stream didn't close socket");
clientSocket.close();
}
log.info("Sleeping ...");
Thread.sleep(5000);
}
}