@Test
public void testRemoteAndSelfGateways() throws Exception {

	final UUID initialFencingToken = UUID.randomUUID();
	final UUID newFencingToken = UUID.randomUUID();
	final String value = "foobar";
	final FencedTestingEndpoint fencedTestingEndpoint = new FencedTestingEndpoint(rpcService, value, initialFencingToken);
	try {
		fencedTestingEndpoint.start();
		FencedTestingGateway selfGateway = fencedTestingEndpoint.getSelfGateway(FencedTestingGateway.class);
		FencedTestingGateway remoteGateway = rpcService.connect(fencedTestingEndpoint.getAddress(), initialFencingToken, FencedTestingGateway.class)
			.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
		assertEquals(initialFencingToken, selfGateway.getFencingToken());
		assertEquals(initialFencingToken, remoteGateway.getFencingToken());
		assertEquals(value, selfGateway.foobar(timeout).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS));
		assertEquals(value, remoteGateway.foobar(timeout).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS));
		CompletableFuture<Acknowledge> newFencingTokenFuture = fencedTestingEndpoint.setFencingTokenInMainThread(newFencingToken, timeout);
		// wait for the new fencing token to be set
		newFencingTokenFuture.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
		assertEquals(newFencingToken, selfGateway.getFencingToken());
		assertNotEquals(newFencingToken, remoteGateway.getFencingToken());
		assertEquals(value, selfGateway.foobar(timeout).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS));
		try {
			remoteGateway.foobar(timeout).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
			fail("This should have failed because we don't have the right fencing token.");
		} catch (ExecutionException e) {
			assertTrue(ExceptionUtils.stripExecutionException(e) instanceof FencingTokenException);
		}
	} finally {
		fencedTestingEndpoint.shutDown();
		fencedTestingEndpoint.getTerminationFuture().get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
	}
}