package com.googlecode.jsonrpc4j.integration; import com.googlecode.jsonrpc4j.JsonRpcBasicServer; import com.googlecode.jsonrpc4j.JsonRpcClient; import com.googlecode.jsonrpc4j.ProxyUtil; import com.googlecode.jsonrpc4j.StreamServer; import com.googlecode.jsonrpc4j.StreamServer.Server; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ServerSocketFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import static com.googlecode.jsonrpc4j.util.Util.DEFAULT_LOCAL_HOSTNAME; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; public class StreamServerTest { private static final Logger logger = LoggerFactory.getLogger(StreamServerTest.class); private ServerSocket serverSocket; private JsonRpcBasicServer jsonRpcServer; private JsonRpcClient jsonRpcClient; private ServiceImpl service; @Before public void setUp() throws Exception { serverSocket = ServerSocketFactory.getDefault().createServerSocket(0, 0, InetAddress.getByName(DEFAULT_LOCAL_HOSTNAME)); service = new ServiceImpl(); jsonRpcServer = new JsonRpcBasicServer(service, Service.class); jsonRpcClient = new JsonRpcClient(); } @Test public void testBasicConnection() throws Exception { StreamServer streamServer = createAndStartServer(); Socket socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); Service client = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), Service.class, jsonRpcClient, socket); for (int i = 0; i < 100; i++) { assertEquals(i, client.inc()); } assertEquals("hello dude", client.hello("dude")); socket.close(); streamServer.stop(); } private StreamServer createAndStartServer() { StreamServer streamServer = new StreamServer(jsonRpcServer, 5, serverSocket); streamServer.start(); return streamServer; } @Test public void testMultipleClients() throws Exception { StreamServer streamServer = createAndStartServer(); CreateClients createClients = new CreateClients().invoke(); Service[] services = createClients.getServices(); Socket[] sockets = createClients.getSockets(); for (Service service2 : services) { for (int j = 0; j < 100; j++) { assertEquals(j, service2.inc()); } service2.reset(); } for (Service service1 : services) { assertEquals("hello dude", service1.hello("dude")); } stopClients(sockets); streamServer.stop(); } private void stopClients(Socket[] sockets) throws IOException { for (Socket socket : sockets) { socket.close(); } } @Test public void testStopWhileClientsWorking() throws Exception { StreamServer streamServer = createAndStartServer(); Socket socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); final Service service1 = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), Service.class, jsonRpcClient, socket); Thread t = new Thread(new Runnable() { @Override public void run() { // noinspection InfiniteLoopStatement while (true) { service1.inc(); } } }); t.start(); while (service.val < 10) { Thread.yield(); } streamServer.stop(); } @Test public void testClientDisconnectsCausingExceptionOnServer() throws Exception { StreamServer streamServer = createAndStartServer(); final Socket socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); final Service service1 = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), Service.class, jsonRpcClient, socket); Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { if (service1.inc() > 5) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } return; } } } }); Thread.sleep(1000); assertEquals(1, streamServer.getNumberOfConnections()); Server server = streamServer.getServers().iterator().next(); assertNotNull(server); t.start(); while (streamServer.getNumberOfConnections() > 0) { Thread.yield(); } assertEquals(0, server.getNumberOfErrors()); streamServer.stop(); } // @Test // Separating invoke() and readResponse() calls #20 // this just isn't going to work with jackson @SuppressWarnings("unused") public void testMultipleClientCallsBeforeReadResponse() throws Throwable { StreamServer streamServer = createAndStartServer(); Socket socket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); InputStream ips = socket.getInputStream(); OutputStream ops = socket.getOutputStream(); for (int i = 0; i < 10; i++) { jsonRpcClient.invoke("inc", null, ops); } for (int i = 0; i < 10; i++) { Integer value = jsonRpcClient.readResponse(Integer.class, ips); assertEquals(i, value.intValue()); } socket.close(); while (streamServer.getNumberOfConnections() > 0) { Thread.yield(); } streamServer.stop(); } @SuppressWarnings("WeakerAccess") public interface Service { String hello(String whatever); int inc(); void reset(); } @SuppressWarnings("WeakerAccess") public static class ServiceImpl implements Service { private int val; public String hello(String whatever) { logger.info("server: hello({})", whatever); return "hello " + whatever; } public int inc() { logger.info("server: inc():", val); return val++; } public void reset() { val = 0; } } private class CreateClients { private Service[] services; private Socket[] sockets; Service[] getServices() { return services; } Socket[] getSockets() { return sockets; } CreateClients invoke() throws IOException { services = new Service[5]; sockets = new Socket[5]; for (int i = 0; i < services.length; i++) { sockets[i] = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort()); services[i] = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), Service.class, jsonRpcClient, sockets[i]); } return this; } } }