/*
* Copyright 2015 Evgeny Dolganov (evgenij.dolganov@gmail.com).
*
* 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 och.util.socket.pool;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashSet;
import och.junit.AssertExt;
import och.util.socket.pool.SocketConn;
import och.util.socket.pool.SocketConnHandler;
import och.util.socket.pool.SocketsPool;
import och.util.socket.server.SocketServer;
import och.util.socket.server.SocketWriterHander;
import org.junit.Ignore;
import org.junit.Test;
import test.TestException;
import static och.util.socket.SocketUtil.*;
public class SocketsPoolTest extends AssertExt {
String host = "localhost";
int port = 11001;
int maxThreads = 10;
@Test
public void test_client_exception() throws Exception {
SocketServer server = createEchoServer(port, 1);
server.runAsync();
try {
SocketsPool pool = new SocketsPool(host, port);
pool.setPoolMaximumActiveConnections(1);
pool.setPoolMaximumIdleConnections(1);
try {
pool.invoke(new SocketConnHandler<Void>() {
@Override
public Void handle(SocketConn c) throws IOException {
c.getWriter().println("test1");
throw new TestException();
}
});
fail_exception_expected();
}catch (TestException e) {
//ok
}
assertEquals(0, pool.getIdleConnections());
pool.invoke(new SocketConnHandler<Void>() {
@Override
public Void handle(SocketConn c) throws IOException {
c.getWriter().println("test2");
assertEquals("test2", c.getReader().readLine());
return null;
}
});
assertEquals(1, pool.getIdleConnections());
} finally {
server.shutdownWait();
}
}
@Test
public void test_client_SocketTimeoutException_fix() throws Exception {
class Context {
volatile boolean needSleep = true;
}
final Context cx = new Context();
final int maxSleep = 100;
final int waitSleep = 50;
SocketServer server = new SocketServer(port, maxThreads, new SocketWriterHander() {
@Override
protected void process(Socket openedSocket, BufferedReader socketReader, PrintWriter socketWriter, SocketServer owner) throws Throwable {
while( ! owner.wasShutdown()){
String line = socketReader.readLine();
try {
if(cx.needSleep) Thread.sleep(maxSleep);
}catch (Exception e) {
e.printStackTrace();
}
if(line == null || owner.wasShutdown()) break;
socketWriter.println(line);
}
}
});
server.runAsync();
try {
SocketsPool pool = new SocketsPool(host, port);
pool.setSocketSoTimeoutForNewConn(waitSleep);
try {
pool.invoke(new SocketConnHandler<Void>() {
@Override
public Void handle(SocketConn c) throws IOException {
c.getWriter().println("test1");
c.getReader().readLine();
return null;
}
});
fail_exception_expected();
}catch (SocketTimeoutException e) {
//ok
}
assertEquals(0, pool.getIdleConnections()); //<------------------ no active connections after exception
} finally {
server.shutdownWait();
}
}
@Ignore
@Test
public void test_client_SocketTimeoutException_wrong_conn_data() throws Exception {
class Context {
volatile boolean needSleep = true;
}
final Context cx = new Context();
final int maxSleep = 300;
final int waitSleep = 200;
SocketServer server = new SocketServer(port, maxThreads, new SocketWriterHander() {
@Override
protected void process(Socket openedSocket, BufferedReader socketReader, PrintWriter socketWriter, SocketServer owner) throws Throwable {
while( ! owner.wasShutdown()){
String line = socketReader.readLine();
try {
if(cx.needSleep) Thread.sleep(maxSleep);
}catch (Exception e) {
e.printStackTrace();
}
if(line == null || owner.wasShutdown()) break;
socketWriter.println(line);
}
}
});
server.runAsync();
try {
SocketsPool pool = new SocketsPool(host, port);
pool.setSocketSoTimeoutForNewConn(waitSleep);
try(SocketConn c = pool.getConnection()){
c.getWriter().println("test1");
c.getReader().readLine();
fail_exception_expected();
} catch (SocketTimeoutException e) {
//ok
}
assertEquals(1, pool.getIdleConnections());
cx.needSleep = false;
try(SocketConn c = pool.getConnection()){
c.getWriter().println("test2");
String oldData = c.getReader().readLine();
assertEquals("test1", oldData); //<-------------------------- !!!
}
} finally {
server.shutdownWait();
}
}
@Test
public void test_lost_conn_and_get_again() throws Exception{
SocketServer server = createEchoServer(port, maxThreads);
server.runAsync();
SocketsPool pool = new SocketsPool(host, port);
pool.setPoolMaximumActiveConnections(1);
pool.setPoolMaximumIdleConnections(1);
try(SocketConn c = pool.getConnection()){
PrintWriter w = c.getWriter();
BufferedReader r = c.getReader();
w.println("1");
assertEquals("1", r.readLine());
//shutdown server
server.shutdownWait();
w.println("1");
assertNull(r.readLine());
}catch (SocketException e) {
//ok
}
SocketConn c = pool.getConnection();
try{
c.getWriter().println("1");
assertNull(c.getReader().readLine());
}catch (SocketException e) {
//ok
}finally {
c.invalidate(); //<-----------------------------
c.close();
}
SocketServer server2 = createEchoServer(port, maxThreads);
server2.runAsync();
try(SocketConn c2 = pool.getConnection()){
c2.getWriter().println("1");
assertEquals("1", c2.getReader().readLine());
}finally {
server2.shutdownWait();
}
}
@Ignore
@Test
public void test_lost_conn_and_get_new() throws Exception{
SocketServer server = createEchoServer(port, maxThreads);
server.runAsync();
SocketsPool pool = new SocketsPool(host, port);
SocketConn c = pool.getConnection();
getWriterUTF8(c.getOutputStream()).println("hello");
assertEquals("hello", getReaderUTF8(c.getInputStream()).readLine());
server.shutdownWait();
try {
pool.getConnection();
fail_exception_expected();
}catch (ConnectException e) {
//ok
}
//server is available again
server = createEchoServer(port, 10);
server.runAsync();
SocketConn c2 = pool.getConnection();
getWriterUTF8(c2.getOutputStream()).println("hello");
assertEquals("hello", getReaderUTF8(c2.getInputStream()).readLine());
server.shutdownWait();
}
@Ignore
@Test(expected=ConnectException.class)
public void test_wrong_url() throws Exception {
SocketsPool pool = new SocketsPool(host, port+1);
pool.getConnection();
}
@Test
public void test_more_than_max_client_conns() throws Exception{
SocketServer server = createEchoServer(port, maxThreads);
server.runAsync();
SocketsPool pool = new SocketsPool(host, port);
int maxConns = maxThreads;
pool.setPoolMaximumIdleConnections(maxConns);
pool.setPoolMaximumActiveConnections(maxConns);
pool.setPoolTimeToWait(5);
pool.setPoolMaximumCheckoutTime(5);
//max conn
HashSet<SocketConn> openConns = new HashSet<>();
for (int i = 0; i < maxConns; i++) {
SocketConn c = pool.getConnection();
boolean isNew = openConns.add(c);
assertTrue(c.toString(), isNew);
}
//more then max - get conn from other client
SocketConn moreThanMax = pool.getConnection();
assertTrue(openConns.contains(moreThanMax));
server.shutdownWait();
}
@Test
public void test_get_conn() throws Exception{
SocketServer server = createEchoServer(port, maxThreads);
server.runAsync();
assertEquals(0, server.getActiveConnectionsCount());
SocketsPool pool = new SocketsPool(host, port);
int maxConns = maxThreads;
pool.setPoolMaximumIdleConnections(maxConns);
pool.setPoolMaximumActiveConnections(maxConns);
//single conn
try(SocketConn c = pool.getConnection()){
getWriterUTF8(c.getOutputStream()).println("hello");
assertEquals("hello", getReaderUTF8(c.getInputStream()).readLine());
assertEquals(1, server.getActiveConnectionsCount());
}
assertEquals(1, server.getActiveConnectionsCount());
try(SocketConn c = pool.getConnection()){
getWriterUTF8(c.getOutputStream()).println("2");
assertEquals("2", getReaderUTF8(c.getInputStream()).readLine());
assertEquals(1, server.getActiveConnectionsCount());
}
//max conn
ArrayList<SocketConn> openConns = new ArrayList<>();
for (int i = 0; i < maxConns; i++) {
openConns.add(pool.getConnection());
}
for (int i = 0; i < maxConns; i++) {
SocketConn c = openConns.get(i);
try{
String msg = "привет-"+i;
getWriterUTF8(c.getOutputStream()).println(msg);
assertEquals(msg, getReaderUTF8(c.getInputStream()).readLine());
}finally {
c.close();
}
}
assertEquals(maxConns, server.getActiveConnectionsCount());
server.shutdownWait();
}
public SocketServer createEchoServer(int port, int maxThreads) {
SocketServer server = new SocketServer(port, maxThreads, new SocketWriterHander() {
@Override
protected void process(Socket openedSocket, BufferedReader socketReader, PrintWriter socketWriter, SocketServer owner) throws Throwable {
while( ! owner.wasShutdown()){
String line = socketReader.readLine();
if(line == null || owner.wasShutdown()) break;
socketWriter.println(line);
}
}
});
return server;
}
}