/*
* Copyright (c) 2012-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.coordinator.client.service;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.rmi.RmiServiceExporter;
import com.emc.storageos.coordinator.client.beacon.ServiceBeacon;
import com.emc.storageos.coordinator.common.Service;
import com.emc.storageos.coordinator.common.impl.ServiceImpl;
import com.emc.storageos.coordinator.exceptions.CoordinatorException;
import com.emc.storageos.coordinator.exceptions.FatalCoordinatorException;
import com.emc.storageos.svcs.errorhandling.resources.ServiceCode;
/**
* Tests beacon and RMI endpoint failover
*/
public class BeaconTest extends CoordinatorTestBase {
private static final Logger _log = LoggerFactory.getLogger(BeaconTest.class);
/**
* Dummy service interface
*/
public interface DummyService {
public void test();
}
/**
* Dummy service impl with noop RMI endpoint
*/
public class DummyServiceImpl implements DummyService {
private ServiceImpl _svc;
private ServiceBeacon _beacon;
private int _port;
private RmiServiceExporter _rmiExport;
public DummyServiceImpl(int port, String tag, String endpointKey) {
_svc = new ServiceImpl();
_svc.setName("dummysvc");
_svc.setVersion("1");
_svc.setId(UUID.randomUUID().toString());
_svc.setTag(tag);
Map<String, URI> endpoint = new HashMap<String, URI>();
URI endpointUri = URI.create(String.format("rmi://localhost:%1$d/test", port));
endpoint.put(endpointKey, endpointUri);
_svc.setEndpointMap(endpoint);
_port = port;
}
public Service getServiceInfo() {
return _svc;
}
public void test() {
_log.info("Test method called");
}
public void start(int timeoutMs) throws Exception {
_beacon = createBeacon(_svc, timeoutMs);
_beacon.start();
}
public void stop() {
_beacon.stop();
}
public void startRmiServer() throws Exception {
_rmiExport = new RmiServiceExporter();
_rmiExport.setServiceName("test");
_rmiExport.setServiceInterface(DummyService.class);
_rmiExport.setRegistryPort(_port);
_rmiExport.setService(this);
_rmiExport.afterPropertiesSet();
}
public void stopRmiServer() throws Exception {
_rmiExport.destroy();
_rmiExport = null;
}
}
@Test
public void testBeacon() throws Exception {
final String tag = "foo";
final String endpointKey = "key";
DummyServiceImpl service = new DummyServiceImpl(10099, tag, endpointKey);
service.startRmiServer();
service.start(1000 * 5);
Service si = service.getServiceInfo();
CoordinatorClient client = connectClient();
DummyService found = client.locateService(DummyService.class, si.getName(), si.getVersion(), tag, endpointKey);
Assert.assertNotNull(found);
found.test();
List<Service> services = client.locateAllServices(si.getName(), si.getVersion(), tag, endpointKey);
Assert.assertEquals(services.size(), 1);
Assert.assertEquals(services.get(0).getName(), si.getName());
Assert.assertEquals(services.get(0).getVersion(), si.getVersion());
Assert.assertEquals(services.get(0).getEndpoint(), si.getEndpoint());
Assert.assertTrue(services.get(0).isTagged(tag));
Assert.assertEquals(services.get(0).getEndpoint(endpointKey), si.getEndpoint());
try {
client.locateService(DummyService.class, si.getName(), si.getVersion(), "random", endpointKey);
assert false;
} catch (CoordinatorException expected) {
// ignore this exception since it's expected
}
try {
client.locateService(DummyService.class, si.getName(), si.getVersion(), tag, "random");
assert false;
} catch (CoordinatorException expected) {
_log.info("CoordinatorException is throwed as we expected", expected);
}
service.stopRmiServer();
service.stop();
}
@Test
public void testRmiFailover() throws Exception {
final String tag = "foo";
final String endpointKey = "bar";
DummyServiceImpl service = new DummyServiceImpl(10100, tag, endpointKey);
service.startRmiServer();
service.start(1000 * 10);
DummyServiceImpl service2 = new DummyServiceImpl(10101, tag, endpointKey);
service2.startRmiServer();
service2.start(1000 * 10);
Service si = service.getServiceInfo();
CoordinatorClient client = connectClient();
DummyService found = client.locateService(DummyService.class, si.getName(), si.getVersion(), tag, endpointKey);
Assert.assertNotNull(found);
found.test();
service.stopRmiServer();
for (int index = 0; index < 100; index++) {
found.test();
}
service2.stopRmiServer();
try {
found.test();
Assert.fail("Expected service lookup to fail");
} catch (FatalCoordinatorException ignore) {
Assert.assertEquals(ServiceCode.COORDINATOR_ERROR, ignore.getServiceCode());
}
service2.startRmiServer();
found.test();
}
}