/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.testutils.templates; import static de.rcenvironment.core.communication.rpc.internal.MethodCallTestInterface.DEFAULT_RESULT_OR_MESSAGE_STRING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; import java.io.Serializable; import java.util.Set; import org.junit.Test; import de.rcenvironment.core.communication.api.NodeIdentifierService; import de.rcenvironment.core.communication.api.ServiceCallContext; import de.rcenvironment.core.communication.api.ServiceCallContextUtils; import de.rcenvironment.core.communication.channel.MessageChannelState; import de.rcenvironment.core.communication.common.IdentifierException; import de.rcenvironment.core.communication.common.InstanceNodeSessionId; import de.rcenvironment.core.communication.common.NodeIdentifierContextHolder; import de.rcenvironment.core.communication.common.NodeIdentifierTestUtils; import de.rcenvironment.core.communication.connection.api.ConnectionSetup; import de.rcenvironment.core.communication.connection.api.ConnectionSetupState; import de.rcenvironment.core.communication.connection.api.DisconnectReason; import de.rcenvironment.core.communication.management.RemoteBenchmarkService; import de.rcenvironment.core.communication.model.NetworkContactPoint; import de.rcenvironment.core.communication.model.NetworkRequest; import de.rcenvironment.core.communication.model.NetworkResponse; import de.rcenvironment.core.communication.protocol.NetworkRequestFactory; import de.rcenvironment.core.communication.protocol.ProtocolConstants.ResultCode; import de.rcenvironment.core.communication.rpc.internal.MethodCallTestInterface; import de.rcenvironment.core.communication.rpc.internal.MethodCallTestInterfaceImpl; import de.rcenvironment.core.communication.testutils.AbstractVirtualInstanceTest; import de.rcenvironment.core.communication.testutils.VirtualInstance; import de.rcenvironment.core.communication.testutils.VirtualInstanceGroup; import de.rcenvironment.core.communication.transport.spi.MessageChannel; import de.rcenvironment.core.communication.transport.virtual.testutils.VirtualTopology; import de.rcenvironment.core.communication.utils.MessageUtils; import de.rcenvironment.core.utils.common.rpc.RemotableService; import de.rcenvironment.core.utils.common.rpc.RemoteOperationException; import de.rcenvironment.core.utils.common.security.AllowRemoteAccess; /** * Base class providing common tests using virtual node instances. "Common" tests are those that do not depend on duplex vs. non-duplex * mode. This may also include test that require duplex mode, and are skipped/ignored when the tested transport does not support this. * * @author Robert Mischke */ public abstract class AbstractCommonVirtualInstanceTest extends AbstractVirtualInstanceTest { /** * {@link DummyTestService} implementation that captures the {@link ServiceCallContext} of the last inbound method invocation. * * @author Robert Mischke */ public static final class ServiceCallContextCatcherImpl implements DummyTestService { private volatile ServiceCallContext lastServiceCallContext; @Override @AllowRemoteAccess public void dummyCall() { lastServiceCallContext = ServiceCallContextUtils.getCurrentServiceCallContext(); } public ServiceCallContext getLastServiceCallContext() { return lastServiceCallContext; } /** * Clears the last captured {@link ServiceCallContext} to prevent test artifacts. */ public void reset() { lastServiceCallContext = null; } } private static final int DEFAULT_TEST_TIMEOUT = 20000; private static final int DIRECT_MESSAGING_TEST_TIMEOUT = 5000; private static final int DEFAULT_STATE_CHANGE_TIMEOUT = 5000; private static final int WAIT_TIME_BEFORE_ASSUMING_CONNECTION_INITIATED = 500; /** * Test with two clients connecting to a single server. The server instance is started before and shut down after the clients. * * @throws Exception on unexpected test exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testBasicClientServer() throws Exception { // TODO old test; could be improved by using new test utilities VirtualInstance client1 = new VirtualInstance("Client1"); VirtualInstance client2 = new VirtualInstance("Client2"); VirtualInstance server = new VirtualInstance("Server"); VirtualInstanceGroup allInstances = new VirtualInstanceGroup(server, client1, client2); VirtualInstanceGroup clients = new VirtualInstanceGroup(client1, client2); allInstances.registerNetworkTransportProvider(transportProvider); addGlobalTrafficListener(allInstances); NetworkContactPoint serverContactPoint = contactPointGenerator.createContactPoint(); server.addServerConfigurationEntry(serverContactPoint); server.start(); // TODO validate server network knowledge, internal state etc. prepareWaitForNextMessage(); // configure & start clients clients.addInitialNetworkPeer(serverContactPoint); clients.start(); // wait for network traffic to end // FIXME check: this succeeds on its own, but fails when run together with other tests waitForNextMessage(); waitForNetworkSilence(); // Systemx.out.println(NetworkFormatter.summary(client1.getTopologyMap())); // Systemx.out.println(NetworkFormatter.summary(client2.getTopologyMap())); // Systemx.out.println(NetworkFormatter.summary(server.getTopologyMap())); // TODO validate server/client network knowledge, internal state etc. prepareWaitForNextMessage(); // stop clients clients.shutDown(); // wait for network traffic to end waitForNextMessage(); waitForNetworkSilence(); // TODO validate server network knowledge, internal state etc. allInstances.shutDown(); } /** * Verifies that a connection is refused if the version strings do not match. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testConnectionRefusedOnVersionMismatch() throws Exception { VirtualInstance client = new VirtualInstance("client"); VirtualInstance server = new VirtualInstance("server"); client.registerNetworkTransportProvider(transportProvider); server.registerNetworkTransportProvider(transportProvider); NetworkContactPoint serverNCP = contactPointGenerator.createContactPoint(); server.addServerConfigurationEntry(serverNCP); client.simulateCustomProtocolVersion("wrongClientVersion"); server.start(); client.start(); ConnectionSetup connection = client.connectAsync(serverNCP); // wait until the connection should have left the initial DISCONNECTED state Thread.sleep(WAIT_TIME_BEFORE_ASSUMING_CONNECTION_INITIATED); connection.awaitState(ConnectionSetupState.DISCONNECTED, DEFAULT_STATE_CHANGE_TIMEOUT); // note: if the "reason" is null, the above sleep() time may be too short assertEquals(DisconnectReason.FAILED_TO_CONNECT, connection.getDisconnectReason()); client.shutDown(); server.shutDown(); } /** * Tests details of channel lifecycle and operation. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testChannelHandling() throws Exception { // 3 instances using duplex connections setupInstances(3, true, true); VirtualInstance client1 = testTopology.getInstance(0); VirtualInstance server = testTopology.getInstance(1); VirtualInstance client2 = testTopology.getInstance(2); testTopology.connect(0, 1); testTopology.connect(2, 1); testTopology.waitUntilReachable(0, 1, DEFAULT_NODE_REACHABILITY_TIMEOUT); testTopology.waitUntilReachable(2, 1, DEFAULT_NODE_REACHABILITY_TIMEOUT); Set<MessageChannel> client1Outgoing = client1.getMessageChannelService().getAllOutgoingChannels(); Set<MessageChannel> client2Outgoing = client2.getMessageChannelService().getAllOutgoingChannels(); Set<MessageChannel> serverOutgoing = server.getMessageChannelService().getAllOutgoingChannels(); assertEquals(1, client1Outgoing.size()); assertEquals(1, client2Outgoing.size()); assertEquals(2, serverOutgoing.size()); MessageChannel channel1toS = client1Outgoing.iterator().next(); MessageChannel channel2toS = client2Outgoing.iterator().next(); // identify/assign outgoing channels of server MessageChannel channelSto1 = null; MessageChannel channelSto2 = null; for (MessageChannel channel : serverOutgoing) { InstanceNodeSessionId remoteNodeId = channel.getRemoteNodeInformation().getInstanceNodeSessionId(); if (remoteNodeId.equals(client1.getInstanceNodeSessionId())) { channelSto1 = channel; } else if (remoteNodeId.equals(client2.getInstanceNodeSessionId())) { channelSto2 = channel; } else { fail(); } } assertNotNull(channelSto1); assertNotNull(channelSto2); // ids assigned? assertNotNull(channel1toS.getChannelId()); assertNotNull(channel2toS.getChannelId()); assertNotNull(channelSto1.getChannelId()); assertNotNull(channelSto2.getChannelId()); // correct "mirror" ids associated? assertEquals(channelSto1.getChannelId(), channel1toS.getAssociatedMirrorChannelId()); assertEquals(channelSto2.getChannelId(), channel2toS.getAssociatedMirrorChannelId()); assertEquals(channel1toS.getChannelId(), channelSto1.getAssociatedMirrorChannelId()); assertEquals(channel2toS.getChannelId(), channelSto2.getAssociatedMirrorChannelId()); // check initial channel states for (VirtualInstance vi : testTopology.getInstances()) { for (MessageChannel channel : vi.getMessageChannelService().getAllOutgoingChannels()) { assertEquals(MessageChannelState.ESTABLISHED, channel.getState()); assertTrue(channel.isReadyToUse()); } } // close a client-to-server connection channel1toS.close(); // may or may not produce network traffic, so wait Thread.sleep(testConfiguration.getDefaultNetworkSilenceWait()); waitForNetworkSilence(); assertEquals(MessageChannelState.CLOSED, channel1toS.getState()); assertEquals(MessageChannelState.CLOSED, channelSto1.getState()); assertEquals(MessageChannelState.ESTABLISHED, channel2toS.getState()); assertEquals(MessageChannelState.ESTABLISHED, channelSto2.getState()); // close a server-to-client connection channelSto2.close(); // may or may not produce network traffic, so wait Thread.sleep(testConfiguration.getDefaultNetworkSilenceWait()); waitForNetworkSilence(); assertEquals(MessageChannelState.CLOSED, channel2toS.getState()); assertEquals(MessageChannelState.CLOSED, channelSto2.getState()); testTopology.getAsGroup().shutDown(); } /** * Tests that result codes are transported back to the client, and properly mapped back into the {@link NetworkResponse} instances. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testResultCodeTransferFromRemoteNodes() throws Exception { // 2 instances using duplex connections setupInstances(2, true, true); VirtualInstance client1 = testTopology.getInstance(0); testTopology.connectAndWait(0, 1, DEFAULT_NODE_REACHABILITY_TIMEOUT); MessageChannel client1ToServer = client1.getMessageChannelService().getAllOutgoingChannels().iterator().next(); // create a request from client1 to client2 byte[] messageBody = MessageUtils.serializeSafeObject("dummy content"); String messageType = "rpc"; // only relevant for sanity checks while routing (ie it must be a message type allowed for forwarding) InstanceNodeSessionId bogusTargetNodeId = NodeIdentifierTestUtils.createTestInstanceNodeSessionIdWithDisplayName("bogus_node_id"); NetworkRequest testRequest = NetworkRequestFactory.createNetworkRequest(messageBody, messageType, client1.getInstanceNodeSessionId(), bogusTargetNodeId); // force sending the message from client1 to server, although a client would not usually do this (as it knows no route to the bogus // target id); this is expected to fail on the server, as the server does not know a valid route either NetworkResponse testResponse = client1.getMessageChannelService().sendDirectMessageBlocking(testRequest, client1ToServer, DIRECT_MESSAGING_TEST_TIMEOUT); assertEquals(ResultCode.NO_ROUTE_TO_DESTINATION_WHILE_FORWARDING, testResponse.getResultCode()); // TODO needed to prevent unnecessary waiting; try to integrate this into the common test setup. (this will probably be easier once // "graceful shutdown" behavior is implemented.) for (VirtualInstance vi : testTopology.getInstances()) { for (MessageChannel channel : vi.getMessageChannelService().getAllOutgoingChannels()) { channel.close(); } } testTopology.getAsGroup().shutDown(); } /** * Tests various aspects of connecting to a network with the same instance node id, but changing session parts, simulating node * restarts. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testSessionIdHandling() throws Exception { VirtualInstance server = new VirtualInstance("s", true); NetworkContactPoint serverNCP = contactPointGenerator.createContactPoint(); server.addServerConfigurationEntry(serverNCP); VirtualInstance client1 = new VirtualInstance("c1"); VirtualInstance client2a = new VirtualInstance("c2a"); VirtualInstance client2b = new VirtualInstance(client2a.getPersistentInstanceNodeId().getInstanceNodeIdString(), "c2b", true); VirtualInstance client2c = new VirtualInstance(client2a.getPersistentInstanceNodeId().getInstanceNodeIdString(), "c2c", true); testTopology = new VirtualTopology(client1, client2a, server, client2b, client2c); testTopology.getAsGroup().registerNetworkTransportProvider(transportProvider); testTopology.getAsGroup().start(); assertTrue(client2a.getPersistentInstanceNodeId().equals(client2b.getPersistentInstanceNodeId())); assertFalse(client2a.getInstanceNodeSessionId().equals(client2b.getInstanceNodeSessionId())); assertTrue(client2a.getPersistentInstanceNodeId().equals(client2c.getPersistentInstanceNodeId())); assertFalse(client2a.getInstanceNodeSessionId().equals(client2c.getInstanceNodeSessionId())); assertFalse(client2b.getInstanceNodeSessionId().equals(client2c.getInstanceNodeSessionId())); log.debug(client2a.getInstanceNodeSessionId()); log.debug(client2b.getInstanceNodeSessionId()); log.debug(client2c.getInstanceNodeSessionId()); testTopology.connect(0, 2); testTopology.connect(1, 2); client1.waitUntilContainsInReachableNodes(client2a.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); client2a.waitUntilContainsInReachableNodes(client1.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); assertTrue(client1.containsInReachableNodes(server.getInstanceNodeSessionId())); assertTrue(client1.containsInReachableNodes(client2a.getInstanceNodeSessionId())); assertTrue(client2a.containsInReachableNodes(server.getInstanceNodeSessionId())); assertTrue(client2a.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2b.containsInReachableNodes(server.getInstanceNodeSessionId())); assertFalse(client2b.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2b.containsInReachableNodes(client2a.getInstanceNodeSessionId())); // test the regular case first: disconnect the original client2a client2a.shutDown(); // now connect client2b testTopology.connect(3, 2); client2b.waitUntilContainsInReachableNodes(client1.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); client1.waitUntilContainsInReachableNodes(client2b.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); assertTrue(client1.containsInReachableNodes(server.getInstanceNodeSessionId())); assertFalse(client1.containsInReachableNodes(client2a.getInstanceNodeSessionId())); assertTrue(client1.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(server.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertTrue(client2b.containsInReachableNodes(server.getInstanceNodeSessionId())); assertTrue(client2b.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2b.containsInReachableNodes(client2a.getInstanceNodeSessionId())); assertTrue(server.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(server.containsInReachableNodes(client2a.getInstanceNodeSessionId())); assertTrue(server.containsInReachableNodes(client2b.getInstanceNodeSessionId())); // now test the irregular case the connected client2b is *not* unregistered from the network client2b.simulateCrash(); // connect client2c testTopology.connect(4, 2); client2c.waitUntilContainsInReachableNodes(client1.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); client1.waitUntilContainsInReachableNodes(client2c.getInstanceNodeSessionId(), DEFAULT_NODE_REACHABILITY_TIMEOUT); // note: whether the commented-out lines should be true depends on the pending decision on how to handle // id collisions in the network - let both ids, or the most recent id, or none of them be reachable? - misc_ro, 8.0.0 assertTrue(client1.containsInReachableNodes(server.getInstanceNodeSessionId())); assertFalse(client1.containsInReachableNodes(client2a.getInstanceNodeSessionId())); // assertTrue(client1.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertTrue(client1.containsInReachableNodes(client2c.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(server.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertFalse(client2a.containsInReachableNodes(client2c.getInstanceNodeSessionId())); assertTrue(client2c.containsInReachableNodes(server.getInstanceNodeSessionId())); assertTrue(client2c.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(client2c.containsInReachableNodes(client2a.getInstanceNodeSessionId())); // assertFalse(client2c.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertTrue(server.containsInReachableNodes(client1.getInstanceNodeSessionId())); assertFalse(server.containsInReachableNodes(client2a.getInstanceNodeSessionId())); // assertTrue(server.containsInReachableNodes(client2b.getInstanceNodeSessionId())); assertTrue(server.containsInReachableNodes(client2c.getInstanceNodeSessionId())); testTopology.getAsGroup().shutDown(); } /** * Tests various aspects of remote service call sending and handling. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testRemoteServiceCalls() throws Exception { // 2 instances using duplex connections setupInstances(2, true, true); VirtualInstance client1 = testTopology.getInstance(0); VirtualInstance server = testTopology.getInstance(1); // test the behavior on a service call to an unreachable node testRPCToUnreachableNode(client1, server); testTopology.connectAndWait(0, 1, DEFAULT_NODE_REACHABILITY_TIMEOUT); server.injectService(MethodCallTestInterface.class, new MethodCallTestInterfaceImpl()); testBasicBenchmarkServiceRPC(client1, server); testCustomTestInterfaceRPC(client1, server); // TODO needed to prevent unnecessary waiting; try to integrate this into the common test setup. (this will probably be easier once // "graceful shutdown" behavior is implemented.) for (VirtualInstance vi : testTopology.getInstances()) { for (MessageChannel channel : vi.getMessageChannelService().getAllOutgoingChannels()) { channel.close(); } } testTopology.getAsGroup().shutDown(); } /** * Tests that a {@link ServiceCallContext} is available both on local and remote calls to {@link RemotableService}s. * * @throws Exception on uncaught exceptions */ @Test(timeout = DEFAULT_TEST_TIMEOUT) public void testServiceCallContextAvailability() throws Exception { // 2 instances using duplex connections setupInstances(2, true, true); VirtualInstance client = testTopology.getInstance(0); VirtualInstance server = testTopology.getInstance(1); ServiceCallContextCatcherImpl clientServiceCallCatcher = new ServiceCallContextCatcherImpl(); client.injectService(DummyTestService.class, clientServiceCallCatcher); ServiceCallContextCatcherImpl serverServiceCallCatcher = new ServiceCallContextCatcherImpl(); server.injectService(DummyTestService.class, serverServiceCallCatcher); testTopology.connectAndWait(0, 1, DEFAULT_NODE_REACHABILITY_TIMEOUT); // C->C (local) client.getCommunicationService().getRemotableService(DummyTestService.class, client.getInstanceNodeSessionId()).dummyCall(); assertNull(serverServiceCallCatcher.lastServiceCallContext); assertEquals(client.getInstanceNodeSessionId(), clientServiceCallCatcher.getLastServiceCallContext().getCallingNode() .convertToInstanceNodeSessionId()); assertEquals(client.getInstanceNodeSessionId(), clientServiceCallCatcher.getLastServiceCallContext().getReceivingNode() .convertToInstanceNodeSessionId()); clientServiceCallCatcher.reset(); // C->S client.getCommunicationService().getRemotableService(DummyTestService.class, server.getInstanceNodeSessionId()).dummyCall(); assertNull(clientServiceCallCatcher.lastServiceCallContext); assertEquals(client.getInstanceNodeSessionId(), serverServiceCallCatcher.getLastServiceCallContext().getCallingNode() .convertToInstanceNodeSessionId()); assertEquals(server.getInstanceNodeSessionId(), serverServiceCallCatcher.getLastServiceCallContext().getReceivingNode() .convertToInstanceNodeSessionId()); serverServiceCallCatcher.reset(); // S->S (local) server.getCommunicationService().getRemotableService(DummyTestService.class, server.getInstanceNodeSessionId()).dummyCall(); assertNull(clientServiceCallCatcher.lastServiceCallContext); assertEquals(server.getInstanceNodeSessionId(), serverServiceCallCatcher.getLastServiceCallContext().getCallingNode() .convertToInstanceNodeSessionId()); assertEquals(server.getInstanceNodeSessionId(), serverServiceCallCatcher.getLastServiceCallContext().getReceivingNode() .convertToInstanceNodeSessionId()); serverServiceCallCatcher.reset(); // S->C server.getCommunicationService().getRemotableService(DummyTestService.class, client.getInstanceNodeSessionId()).dummyCall(); assertNull(serverServiceCallCatcher.lastServiceCallContext); assertEquals(server.getInstanceNodeSessionId(), clientServiceCallCatcher.getLastServiceCallContext().getCallingNode() .convertToInstanceNodeSessionId()); assertEquals(client.getInstanceNodeSessionId(), clientServiceCallCatcher.getLastServiceCallContext().getReceivingNode() .convertToInstanceNodeSessionId()); clientServiceCallCatcher.reset(); testTopology.getAsGroup().shutDown(); } private void testRPCToUnreachableNode(VirtualInstance caller, VirtualInstance receiver) throws RemoteOperationException, IdentifierException { // use id handling context of client1 NodeIdentifierService callerNodeIdService = caller.getService(NodeIdentifierService.class); assertNotNull(callerNodeIdService); NodeIdentifierContextHolder.setDeserializationServiceForCurrentThread(callerNodeIdService); log.debug("Performing test RPC from " + caller + " to unreachable target node " + receiver); // detach from the sender's id object by serializing and reconstructing it at the sender InstanceNodeSessionId detachedReceiverInstanceNodeSessionId = callerNodeIdService.parseInstanceNodeSessionIdString(receiver.getInstanceNodeSessionIdString()); // this should succeed; the local proxy does not check for reachability RemoteBenchmarkService benchmarkServiceProxy = caller.getCommunicationService().getRemotableService(RemoteBenchmarkService.class, detachedReceiverInstanceNodeSessionId); try { benchmarkServiceProxy.respond("dummy", 1, 1); failWithExceptionExpectedMessage(); } catch (RemoteOperationException e) { assertTrue(e.getMessage().contains(ResultCode.NO_ROUTE_TO_DESTINATION_AT_SENDER.toString())); // custom message assertTrue(e.getCause() == null); // there should be no stacktraces on the client side } NodeIdentifierContextHolder.setDeserializationServiceForCurrentThread(null); } private void testBasicBenchmarkServiceRPC(VirtualInstance client1, VirtualInstance server) throws RemoteOperationException { RemoteBenchmarkService benchmarkServiceProxy = client1.getCommunicationService().getRemotableService(RemoteBenchmarkService.class, server.getInstanceNodeSessionId()); // test basic RPC operation using the standard benchmark service assertNotNull(benchmarkServiceProxy); final int respSize = 99; Serializable response = benchmarkServiceProxy.respond("dummy", respSize, 1); assertEquals(respSize, ((byte[]) response).length); } private void testCustomTestInterfaceRPC(VirtualInstance client1, VirtualInstance server) throws RemoteOperationException { MethodCallTestInterface remoteProxy = client1.getCommunicationService().getRemotableService(MethodCallTestInterface.class, server.getInstanceNodeSessionId()); assertNotNull(remoteProxy); assertEquals(DEFAULT_RESULT_OR_MESSAGE_STRING, remoteProxy.getString()); final int testInput = 5; assertEquals(testInput + 1, remoteProxy.add(testInput, 1)); try { remoteProxy.ioExceptionThrower(); failWithExceptionExpectedMessage(); } catch (IOException e) { assertEquals(DEFAULT_RESULT_OR_MESSAGE_STRING, e.getMessage()); // custom message assertTrue(e.getCause() == null); // there should be no stacktraces on the client side } try { remoteProxy.runtimeExceptionThrower(); failWithExceptionExpectedMessage(); } catch (RemoteOperationException e) { // TODO check message assertTrue(e.getCause() == null); // there should be no stacktraces arriving on the client side } // check that ambiguous methods are refused try { remoteProxy.ambiguous((Object) "", ""); failWithExceptionExpectedMessage(); } catch (RemoteOperationException e) { assertTrue(e.getMessage(), e.getMessage().contains("refused")); assertTrue(e.getCause() == null); // there should be no stacktraces on the client side } } private void failWithExceptionExpectedMessage() { fail("Exception expected"); } }