/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.rpc;
import org.eclipse.dawnsci.analysis.api.rpc.AnalysisRpcException;
import org.eclipse.dawnsci.analysis.api.rpc.AnalysisRpcRemoteException;
import org.eclipse.dawnsci.analysis.api.rpc.IAnalysisRpcHandler;
import org.junit.Assert;
import org.junit.Test;
public class AnalysisRpcAdvancedTest {
// Increment port on each use to avoid a Windows issue of a significant
// slowdown between starting and then restarting a server
static int PORT = 8615;
@Test
public void testMultipleHandlers() throws AnalysisRpcException {
AnalysisRpcServer analysisRpcServer = null;
try {
analysisRpcServer = new AnalysisRpcServer(++PORT);
analysisRpcServer.start();
analysisRpcServer.addHandler("cat", new IAnalysisRpcHandler() {
@Override
public Object run(Object[] unflattened) {
return (String) unflattened[0] + (String) unflattened[1];
}
});
analysisRpcServer.addHandler("len", new IAnalysisRpcHandler() {
@Override
public Object run(Object[] unflattened) {
return ((String) unflattened[0] + (String) unflattened[1])
.length();
}
});
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(PORT);
String catResult = (String) analysisRpcClient.request("cat",
new Object[] { "Hello, ", "World!" });
Assert.assertEquals("Hello, World!", catResult);
int lenResult = (Integer) analysisRpcClient.request("len",
new Object[] { "Hello, ", "World!" });
Assert.assertEquals("Hello, World!".length(), lenResult);
} finally {
if (analysisRpcServer != null)
analysisRpcServer.shutdown();
}
}
@Test
public void testExceptionOnHandlerFlattening() throws AnalysisRpcException {
AnalysisRpcServer analysisRpcServer = null;
try {
analysisRpcServer = new AnalysisRpcServer(++PORT);
analysisRpcServer.start();
analysisRpcServer.addHandler("flaterror",
new IAnalysisRpcHandler() {
@Override
public Object run(Object[] unflattened) {
// return unflattanble type
return new Object();
}
});
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(PORT);
// force a flattening exception on the call side
try {
analysisRpcClient
.request("flaterror", new Object[] { "Hello" });
Assert.fail("No exception raised");
} catch (AnalysisRpcException e) {
Assert.assertFalse(e.getCause() instanceof UnsupportedOperationException);
Assert.assertTrue(e.getCause() instanceof AnalysisRpcRemoteException);
}
} finally {
if (analysisRpcServer != null)
analysisRpcServer.shutdown();
}
}
// As all comms are to the localhost, we want to make sure we time out
// pretty quickly
@Test(expected = AnalysisRpcException.class, timeout = 2000)
public void testConnectionTimesOutQuicklyEnough()
throws AnalysisRpcException {
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(++PORT);
analysisRpcClient.request("doesnotexist", new Object[] { "Hello" });
}
@Test
public void testIsAlive() throws AnalysisRpcException {
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(++PORT);
Assert.assertFalse(analysisRpcClient.isAlive());
AnalysisRpcServer analysisRpcServer = new AnalysisRpcServer(PORT);
try {
analysisRpcServer.start();
Assert.assertTrue(analysisRpcClient.isAlive());
} finally {
analysisRpcServer.shutdown();
}
}
@Test
public void waitIsAlive() throws AnalysisRpcException {
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(++PORT);
Assert.assertFalse(analysisRpcClient.isAlive());
try {
analysisRpcClient.waitUntilAlive(1000);
Assert.fail();
} catch (AnalysisRpcException e) {
// test passes, waitUntilAlive has raised exception saying not ready
// yet
}
AnalysisRpcServer analysisRpcServer = new AnalysisRpcServer(PORT);
try {
analysisRpcServer.start();
analysisRpcClient.waitUntilAlive(1000);
Assert.assertTrue(analysisRpcClient.isAlive());
} finally {
analysisRpcServer.shutdown();
}
}
interface TestProxy_Interface {
public String cat(String a1, String a2) throws AnalysisRpcException;
}
@Test
public void testProxy() throws AnalysisRpcException {
AnalysisRpcServer analysisRpcServer = null;
try {
analysisRpcServer = new AnalysisRpcServer(++PORT);
analysisRpcServer.start();
analysisRpcServer.addHandler("cat", new IAnalysisRpcHandler() {
@Override
public Object run(Object[] unflattened) {
return (String) unflattened[0] + (String) unflattened[1];
}
});
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(PORT);
TestProxy_Interface catObject = analysisRpcClient
.newProxyInstance(TestProxy_Interface.class);
String catResult = catObject.cat("Hello, ", "World!");
Assert.assertEquals("Hello, World!", catResult);
} finally {
if (analysisRpcServer != null)
analysisRpcServer.shutdown();
}
}
interface TestBadProxy_Interface {
// Missing throws AnalysisRpcException
public String cat(String a1, String a2);
}
/**
* This test makes sure that methods on the interface throws
* AnalysisRpcException. However, it may be desirable to change this
* restriction to a new RuntimeException that does not have this
* requirement. The advantage would be that any interface could be
* implemented in Python (across the server divide) but that would add an
* implication to the user of the interface that the call does not have to
* worry about such issues.
*/
@Test
public void testBadProxy() {
// don't need a real server because this test makes sure the bad proxy
// fails
AnalysisRpcClient analysisRpcClient = new AnalysisRpcClient(++PORT);
TestBadProxy_Interface catObject = analysisRpcClient
.newProxyInstance(TestBadProxy_Interface.class);
try {
catObject.cat("Hello, ", "World!");
Assert.fail("Exception not thrown as expected");
} catch (RuntimeException e) {
}
try {
catObject.equals(null);
Assert.fail("Exception not thrown as expected");
} catch (RuntimeException e) {
}
}
}