X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fremoterpc-routingtable%2Fimplementation%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fconnector%2Fremoterpc%2Fimpl%2FRoutingTableImplTest.java;h=0987df595689176b2d734da6c048ef00a909b2b0;hp=50460d4e5ec897892a9a507a1b48244098887c86;hb=1f2754487ab1e3a37c830909806f90cd54180c7b;hpb=4467f6e1ac869d390b607db90cd7e540118a4c6e diff --git a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java index 50460d4e5e..0987df5956 100644 --- a/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java +++ b/opendaylight/md-sal/remoterpc-routingtable/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/impl/RoutingTableImplTest.java @@ -10,196 +10,321 @@ package org.opendaylight.controller.sal.connector.remoterpc.impl; import junit.framework.Assert; import org.apache.felix.dm.Component; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.clustering.services.IClusterGlobalServices; import org.opendaylight.controller.clustering.services.IClusterServices; import org.opendaylight.controller.sal.connector.api.RpcRouter; -import org.opendaylight.controller.sal.connector.remoterpc.api.RouteChangeListener; +import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable; +import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException; +import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import java.net.URI; import java.util.EnumSet; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.Set; -import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; -/** - * @author: syedbahm - */ public class RoutingTableImplTest { - private IClusterGlobalServices ics = mock(IClusterGlobalServices.class); - private RoutingTableImpl rti = new RoutingTableImpl(); + private final URI namespace = URI.create("http://cisco.com/example"); + private final QName QNAME = new QName(namespace, "global"); - private final URI namespace = URI.create("http://cisco.com/example"); - private final QName QNAME = new QName(namespace,"global"); + private IClusterGlobalServices clusterService; + private RoutingTableImpl, String> routingTable; + ConcurrentMap mockGlobalRpcCache; + ConcurrentMap mockRpcCache; - ConcurrentMap concurrentMapMock = mock(ConcurrentMap.class); + @Before + public void setUp() throws Exception{ + clusterService = mock(IClusterGlobalServices.class); + routingTable = new RoutingTableImpl, String>(); + mockGlobalRpcCache = new ConcurrentHashMap<>(); + mockRpcCache = new ConcurrentHashMap<>(); + createRoutingTableCache(); + } + @After + public void tearDown(){ + reset(clusterService); + mockGlobalRpcCache = null; + mockRpcCache = null; + } - @Test - public void testAddGlobalRoute() throws Exception { - ConcurrentMap concurrentMap = createRoutingTableCache(); + @Test + public void addGlobalRoute_ValidArguments_ShouldAdd() throws Exception { - Assert.assertNotNull(concurrentMap); - RpcRouter.RouteIdentifier routeIdentifier = mock(RpcRouter.RouteIdentifier.class); - InstanceIdentifier identifier = mock(InstanceIdentifier.class); - when(routeIdentifier.getType()).thenReturn(QNAME); - when(routeIdentifier.getRoute()).thenReturn(identifier); + Assert.assertNotNull(mockGlobalRpcCache); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); - rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000"); + final String expectedRoute = "172.27.12.1:5000"; + routingTable.addGlobalRoute(routeIdentifier, expectedRoute); - Set globalService = new HashSet(); - globalService.add("172.27.12.1:5000"); + ConcurrentMap latestCache = routingTable.getGlobalRpcCache(); + Assert.assertEquals(mockGlobalRpcCache, latestCache); + Assert.assertEquals(expectedRoute, latestCache.get(routeIdentifier)); + } - when(concurrentMap.get(routeIdentifier)).thenReturn(globalService); - ConcurrentMap latestCache = rti.getRoutingTableCache(); + @Test (expected = RoutingTable.DuplicateRouteException.class) + public void addGlobalRoute_DuplicateRoute_ShouldThrow() throws Exception{ - Assert.assertEquals(concurrentMap,latestCache); + Assert.assertNotNull(mockGlobalRpcCache); - Set servicesGlobal = (Set)latestCache.get(routeIdentifier); - Assert.assertEquals(servicesGlobal.size(),1); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); + routingTable.addGlobalRoute(routeIdentifier, new String()); + routingTable.addGlobalRoute(routeIdentifier, new String()); + } - Assert.assertEquals(servicesGlobal.iterator().next(),"172.27.12.1:5000"); + @Test + public void getGlobalRoute_ExistingRouteId_ShouldReturnRoute() throws Exception { - } + Assert.assertNotNull(mockGlobalRpcCache); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); + String expectedRoute = "172.27.12.1:5000"; - @Test - public void testGetRoutes() throws Exception { - ConcurrentMap concurrentMap = createRoutingTableCache(); + routingTable.addGlobalRoute(routeIdentifier, expectedRoute); - Assert.assertNotNull(concurrentMap); - RpcRouter.RouteIdentifier routeIdentifier = mock(RpcRouter.RouteIdentifier.class); - InstanceIdentifier identifier = mock(InstanceIdentifier.class); - when(routeIdentifier.getContext()).thenReturn(QNAME); - when(routeIdentifier.getRoute()).thenReturn(identifier); + String actualRoute = (String) routingTable.getGlobalRoute(routeIdentifier); + Assert.assertEquals(expectedRoute, actualRoute); + } - rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000"); + @Test + public void getGlobalRoute_NonExistentRouteId_ShouldReturnNull() throws Exception { - String globalService = "172.27.12.1:5000"; + Assert.assertNotNull(mockGlobalRpcCache); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); - when(concurrentMap.get(routeIdentifier)).thenReturn(globalService); - ConcurrentMap latestCache = rti.getRoutingTableCache(); + String actualRoute = (String) routingTable.getGlobalRoute(routeIdentifier); + Assert.assertNull(actualRoute); + } - Assert.assertEquals(concurrentMap,latestCache); + @Test + public void removeGlobalRoute_ExistingRouteId_ShouldRemove() throws Exception { - Set servicesGlobal = rti.getRoutes(routeIdentifier); + Assert.assertNotNull(mockGlobalRpcCache); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); + ConcurrentMap cache = routingTable.getGlobalRpcCache(); + Assert.assertTrue(cache.size() == 0); + routingTable.addGlobalRoute(routeIdentifier, "172.27.12.1:5000"); + Assert.assertTrue(cache.size() == 1); - Assert.assertEquals(servicesGlobal.size(),1); - Iterator iterator = servicesGlobal.iterator(); - while(iterator.hasNext()){ - Assert.assertEquals(iterator.next(),"172.27.12.1:5000"); - } + routingTable.removeGlobalRoute(routeIdentifier); + Assert.assertTrue(cache.size() == 0); + } - } - @Test - public void testRegisterRouteChangeListener() throws Exception { - Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0); - rti.registerRouteChangeListener(new RouteChangeListenerImpl()); + @Test + public void removeGlobalRoute_NonExistentRouteId_ShouldDoNothing() throws Exception { - Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),0); //old should not work - //what about the new approach - using whiteboard pattern - rti.setRouteChangeListener(new RouteChangeListenerImpl()); + Assert.assertNotNull(mockGlobalRpcCache); + RpcRouter.RouteIdentifier routeIdentifier = getRouteIdentifier(); - Assert.assertEquals(rti.getRegisteredRouteChangeListeners().size(),1); //should not work + ConcurrentMap cache = routingTable.getGlobalRpcCache(); + Assert.assertTrue(cache.size() == 0); + routingTable.removeGlobalRoute(routeIdentifier); + Assert.assertTrue(cache.size() == 0); - } - @Test - public void testRemoveGlobalRoute()throws Exception { + } - ConcurrentMap concurrentMap = createRoutingTableCache(); + @Test + public void addRoute_ForNewRouteId_ShouldAddRoute() throws Exception { + Assert.assertTrue(mockRpcCache.size() == 0); - Assert.assertNotNull(concurrentMap); - RpcRouter.RouteIdentifier routeIdentifier = mock(RpcRouter.RouteIdentifier.class); - InstanceIdentifier identifier = mock(InstanceIdentifier.class); - when(routeIdentifier.getContext()).thenReturn(QNAME); - when(routeIdentifier.getRoute()).thenReturn(identifier); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); - rti.addGlobalRoute(routeIdentifier, "172.27.12.1:5000"); + routingTable.addRoute(routeId, new String()); + Assert.assertTrue(mockRpcCache.size() == 1); - String globalService = "172.27.12.1:5000"; + Set routes = routingTable.getRoutes(routeId); + Assert.assertEquals(1, routes.size()); + } - when(concurrentMap.get(routeIdentifier)).thenReturn(globalService); - ConcurrentMap latestCache = rti.getRoutingTableCache(); + @Test + public void addRoute_ForExistingRouteId_ShouldAppendRoute() throws Exception { - Assert.assertEquals(concurrentMap,latestCache); + Assert.assertTrue(mockRpcCache.size() == 0); - Set servicesGlobal = rti.getRoutes(routeIdentifier); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + String route_1 = "10.0.0.1:5955"; + String route_2 = "10.0.0.2:5955"; - Assert.assertEquals(servicesGlobal.size(),1); + routingTable.addRoute(routeId, route_1); + routingTable.addRoute(routeId, route_2); - Assert.assertEquals(servicesGlobal.iterator().next(),"172.27.12.1:5000"); + Assert.assertTrue(mockRpcCache.size() == 1); - rti.removeGlobalRoute(routeIdentifier); + Set routes = routingTable.getRoutes(routeId); + Assert.assertEquals(2, routes.size()); + Assert.assertTrue(routes.contains(route_1)); + Assert.assertTrue(routes.contains(route_2)); + } - Assert.assertNotNull(rti.getRoutes(routeIdentifier)); + @Test + public void addRoute_UsingMultipleThreads_ShouldNotOverwrite(){ + ExecutorService threadPool = Executors.newCachedThreadPool(); + int numOfRoutesToAdd = 100; + String routePrefix_1 = "10.0.0.1:555"; + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_1, routeId)); + String routePrefix_2 = "10.0.0.1:556"; + threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_2, routeId)); + // wait for all tasks to complete; timeout in 10 sec + threadPool.shutdown(); + try { + threadPool.awaitTermination(10, TimeUnit.SECONDS); // + } catch (InterruptedException e) { + e.printStackTrace(); } - private ConcurrentMap createRoutingTableCache() throws Exception { + Assert.assertEquals(2*numOfRoutesToAdd, routingTable.getRoutes(routeId).size()); + } - //here init - Component c = mock(Component.class); + @Test(expected = NullPointerException.class) + public void addRoute_NullRouteId_shouldThrowNpe() throws Exception { - when(ics.existCache( - RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(false); + routingTable.addRoute(null, new String()); + } - when(ics.createCache(RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(concurrentMapMock); - rti.setClusterGlobalServices(this.ics); - rti.init(c); + @Test(expected = NullPointerException.class) + public void addRoute_NullRoute_shouldThrowNpe() throws Exception{ - Assert.assertEquals(concurrentMapMock,rti.getRoutingTableCache() ); - return concurrentMapMock; + routingTable.addRoute(getRouteIdentifier(), null); + } - } + @Test (expected = UnsupportedOperationException.class) + public void getRoutes_Call_ShouldReturnImmutableCopy() throws Exception{ + Assert.assertNotNull(routingTable); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + routingTable.addRoute(routeId, new String()); + Set routes = routingTable.getRoutes(routeId); //returns Immutable Set - @Test - public void testCreateRoutingTableCacheReturnExistingCache() throws Exception { - ConcurrentMap concurrentMap = createRoutingTableCache(); + routes.add(new String()); //can not be modified; should throw + } - //OK here we should try creating again the cache but this time it should return the existing one - when(ics.existCache( - RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(true); + @Test + public void getRoutes_With2RoutesFor1RouteId_ShouldReturnASetWithSize2() throws Exception{ + Assert.assertNotNull(routingTable); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + routingTable.addRoute(routeId, "10.0.0.1:5555"); + routingTable.addRoute(routeId, "10.0.0.2:5555"); - when(ics.getCache( - RoutingTableImpl.ROUTING_TABLE_GLOBAL_CACHE)).thenReturn(concurrentMap); + Set routes = routingTable.getRoutes(routeId); //returns Immutable Set + Assert.assertEquals(2, routes.size()); + } - //here init - Component c = mock(Component.class); + @Test + public void getLastAddedRoute_WhenMultipleRoutesExists_ShouldReturnLatestRoute() + throws Exception { - rti.init(c); + Assert.assertNotNull(routingTable); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + String route_1 = "10.0.0.1:5555"; + String route_2 = "10.0.0.2:5555"; + routingTable.addRoute(routeId, route_1); + routingTable.addRoute(routeId, route_2); - Assert.assertEquals(concurrentMap,rti.getRoutingTableCache()); + Assert.assertEquals(route_2, routingTable.getLastAddedRoute(routeId)); + } + @Test + public void removeRoute_WhenMultipleRoutesExist_RemovesGivenRoute() throws Exception{ + Assert.assertNotNull(routingTable); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + String route_1 = "10.0.0.1:5555"; + String route_2 = "10.0.0.2:5555"; + routingTable.addRoute(routeId, route_1); + routingTable.addRoute(routeId, route_2); + Assert.assertEquals(2, routingTable.getRoutes(routeId).size()); + routingTable.removeRoute(routeId, route_1); + Assert.assertEquals(1, routingTable.getRoutes(routeId).size()); - } + } - private class RouteChangeListenerImpl implements RouteChangeListener{ + @Test + public void removeRoute_WhenOnlyOneRouteExists_RemovesRouteId() throws Exception{ + Assert.assertNotNull(routingTable); + RpcRouter.RouteIdentifier routeId = getRouteIdentifier(); + String route_1 = "10.0.0.1:5555"; - @Override - public void onRouteUpdated(I key, R new_value) { - //To change body of implemented methods use File | Settings | File Templates. - } + routingTable.addRoute(routeId, route_1); + Assert.assertEquals(1, routingTable.getRoutes(routeId).size()); - @Override - public void onRouteDeleted(I key) { - //To change body of implemented methods use File | Settings | File Templates. - } - } + routingTable.removeRoute(routeId, route_1); + ConcurrentMap cache = routingTable.getRpcCache(); + Assert.assertFalse(cache.containsKey(routeId)); + + } + /* + * Private helper methods + */ + private void createRoutingTableCache() throws Exception { + + //here init + Component c = mock(Component.class); + + when(clusterService.existCache( + RoutingTableImpl.GLOBALRPC_CACHE)).thenReturn(false); + + when(clusterService.createCache(RoutingTableImpl.GLOBALRPC_CACHE, + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))). + thenReturn(mockGlobalRpcCache); + + when(clusterService.existCache( + RoutingTableImpl.RPC_CACHE)).thenReturn(false); + + when(clusterService.createCache(RoutingTableImpl.RPC_CACHE, + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))). + thenReturn(mockRpcCache); + + doNothing().when(clusterService).tbegin(); + doNothing().when(clusterService).tcommit(); + + routingTable.setClusterGlobalServices(this.clusterService); + routingTable.init(c); + + Assert.assertEquals(mockGlobalRpcCache, routingTable.getGlobalRpcCache()); + Assert.assertEquals(mockRpcCache, routingTable.getRpcCache()); + } + + private RpcRouter.RouteIdentifier getRouteIdentifier(){ + RpcRouter.RouteIdentifier routeIdentifier = mock(RpcRouter.RouteIdentifier.class); + InstanceIdentifier identifier = mock(InstanceIdentifier.class); + when(routeIdentifier.getType()).thenReturn(QNAME); + when(routeIdentifier.getRoute()).thenReturn(identifier); + + return routeIdentifier; + } + + private Runnable addRoutes(final int numRoutes, final String routePrefix, final RpcRouter.RouteIdentifier routeId){ + return new Runnable() { + @Override + public void run() { + for (int i=0;i