2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.sal.connector.remoterpc.impl;
11 import static org.mockito.Mockito.doNothing;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.reset;
14 import static org.mockito.Mockito.when;
17 import java.util.EnumSet;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ConcurrentMap;
21 import java.util.concurrent.ExecutorService;
22 import java.util.concurrent.Executors;
23 import java.util.concurrent.TimeUnit;
25 import junit.framework.Assert;
27 import org.apache.felix.dm.Component;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
32 import org.opendaylight.controller.clustering.services.IClusterServices;
33 import org.opendaylight.controller.sal.connector.api.RpcRouter;
34 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
35 import org.opendaylight.yangtools.yang.common.QName;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
38 public class RoutingTableImplTest {
40 private final URI namespace = URI.create("http://cisco.com/example");
41 private final QName QNAME = new QName(namespace, "global");
43 private IClusterGlobalServices clusterService;
44 private RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
45 ConcurrentMap mockGlobalRpcCache;
46 ConcurrentMap mockRpcCache;
49 public void setUp() throws Exception{
50 clusterService = mock(IClusterGlobalServices.class);
51 routingTable = new RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
52 mockGlobalRpcCache = new ConcurrentHashMap<>();
53 mockRpcCache = new ConcurrentHashMap<>();
54 createRoutingTableCache();
58 public void tearDown(){
59 reset(clusterService);
60 mockGlobalRpcCache = null;
65 public void addGlobalRoute_ValidArguments_ShouldAdd() throws Exception {
67 Assert.assertNotNull(mockGlobalRpcCache);
68 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
70 final String expectedRoute = "172.27.12.1:5000";
71 routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
73 ConcurrentMap latestCache = routingTable.getGlobalRpcCache();
74 Assert.assertEquals(mockGlobalRpcCache, latestCache);
75 Assert.assertEquals(expectedRoute, latestCache.get(routeIdentifier));
78 @Test (expected = RoutingTable.DuplicateRouteException.class)
79 public void addGlobalRoute_DuplicateRoute_ShouldThrow() throws Exception{
81 Assert.assertNotNull(mockGlobalRpcCache);
83 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
84 routingTable.addGlobalRoute(routeIdentifier, new String());
85 routingTable.addGlobalRoute(routeIdentifier, new String());
89 public void getGlobalRoute_ExistingRouteId_ShouldReturnRoute() throws Exception {
91 Assert.assertNotNull(mockGlobalRpcCache);
92 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
93 String expectedRoute = "172.27.12.1:5000";
95 routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
97 String actualRoute = routingTable.getGlobalRoute(routeIdentifier);
98 Assert.assertEquals(expectedRoute, actualRoute);
102 public void getGlobalRoute_NonExistentRouteId_ShouldReturnNull() throws Exception {
104 Assert.assertNotNull(mockGlobalRpcCache);
105 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
107 String actualRoute = routingTable.getGlobalRoute(routeIdentifier);
108 Assert.assertNull(actualRoute);
112 public void removeGlobalRoute_ExistingRouteId_ShouldRemove() throws Exception {
114 Assert.assertNotNull(mockGlobalRpcCache);
115 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
117 ConcurrentMap cache = routingTable.getGlobalRpcCache();
118 Assert.assertTrue(cache.size() == 0);
119 routingTable.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
120 Assert.assertTrue(cache.size() == 1);
122 routingTable.removeGlobalRoute(routeIdentifier);
123 Assert.assertTrue(cache.size() == 0);
128 public void removeGlobalRoute_NonExistentRouteId_ShouldDoNothing() throws Exception {
130 Assert.assertNotNull(mockGlobalRpcCache);
131 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
133 ConcurrentMap cache = routingTable.getGlobalRpcCache();
134 Assert.assertTrue(cache.size() == 0);
136 routingTable.removeGlobalRoute(routeIdentifier);
137 Assert.assertTrue(cache.size() == 0);
142 public void addRoute_ForNewRouteId_ShouldAddRoute() throws Exception {
143 Assert.assertTrue(mockRpcCache.size() == 0);
145 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
147 routingTable.addRoute(routeId, new String());
148 Assert.assertTrue(mockRpcCache.size() == 1);
150 Set<String> routes = routingTable.getRoutes(routeId);
151 Assert.assertEquals(1, routes.size());
155 public void addRoute_ForExistingRouteId_ShouldAppendRoute() throws Exception {
157 Assert.assertTrue(mockRpcCache.size() == 0);
159 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
161 String route_1 = "10.0.0.1:5955";
162 String route_2 = "10.0.0.2:5955";
164 routingTable.addRoute(routeId, route_1);
165 routingTable.addRoute(routeId, route_2);
167 Assert.assertTrue(mockRpcCache.size() == 1);
169 Set<String> routes = routingTable.getRoutes(routeId);
170 Assert.assertEquals(2, routes.size());
171 Assert.assertTrue(routes.contains(route_1));
172 Assert.assertTrue(routes.contains(route_2));
176 public void addRoute_UsingMultipleThreads_ShouldNotOverwrite(){
177 ExecutorService threadPool = Executors.newCachedThreadPool();
179 int numOfRoutesToAdd = 100;
180 String routePrefix_1 = "10.0.0.1:555";
181 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
182 threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_1, routeId));
183 String routePrefix_2 = "10.0.0.1:556";
184 threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_2, routeId));
186 // wait for all tasks to complete; timeout in 10 sec
187 threadPool.shutdown();
189 threadPool.awaitTermination(10, TimeUnit.SECONDS); //
190 } catch (InterruptedException e) {
194 Assert.assertEquals(2*numOfRoutesToAdd, routingTable.getRoutes(routeId).size());
197 @Test(expected = NullPointerException.class)
198 public void addRoute_NullRouteId_shouldThrowNpe() throws Exception {
200 routingTable.addRoute(null, new String());
203 @Test(expected = NullPointerException.class)
204 public void addRoute_NullRoute_shouldThrowNpe() throws Exception{
206 routingTable.addRoute(getRouteIdentifier(), null);
209 @Test (expected = UnsupportedOperationException.class)
210 public void getRoutes_Call_ShouldReturnImmutableCopy() throws Exception{
211 Assert.assertNotNull(routingTable);
212 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
213 routingTable.addRoute(routeId, new String());
215 Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
217 routes.add(new String()); //can not be modified; should throw
221 public void getRoutes_With2RoutesFor1RouteId_ShouldReturnASetWithSize2() throws Exception{
222 Assert.assertNotNull(routingTable);
223 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
224 routingTable.addRoute(routeId, "10.0.0.1:5555");
225 routingTable.addRoute(routeId, "10.0.0.2:5555");
227 Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
229 Assert.assertEquals(2, routes.size());
233 public void getLastAddedRoute_WhenMultipleRoutesExists_ShouldReturnLatestRoute()
236 Assert.assertNotNull(routingTable);
237 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
238 String route_1 = "10.0.0.1:5555";
239 String route_2 = "10.0.0.2:5555";
240 routingTable.addRoute(routeId, route_1);
241 routingTable.addRoute(routeId, route_2);
243 Assert.assertEquals(route_2, routingTable.getLastAddedRoute(routeId));
247 public void removeRoute_WhenMultipleRoutesExist_RemovesGivenRoute() throws Exception{
248 Assert.assertNotNull(routingTable);
249 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
250 String route_1 = "10.0.0.1:5555";
251 String route_2 = "10.0.0.2:5555";
253 routingTable.addRoute(routeId, route_1);
254 routingTable.addRoute(routeId, route_2);
256 Assert.assertEquals(2, routingTable.getRoutes(routeId).size());
258 routingTable.removeRoute(routeId, route_1);
259 Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
264 public void removeRoute_WhenOnlyOneRouteExists_RemovesRouteId() throws Exception{
265 Assert.assertNotNull(routingTable);
266 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
267 String route_1 = "10.0.0.1:5555";
269 routingTable.addRoute(routeId, route_1);
270 Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
272 routingTable.removeRoute(routeId, route_1);
273 ConcurrentMap cache = routingTable.getRpcCache();
274 Assert.assertFalse(cache.containsKey(routeId));
279 * Private helper methods
281 private void createRoutingTableCache() throws Exception {
284 Component c = mock(Component.class);
286 when(clusterService.existCache(
287 RoutingTableImpl.GLOBALRPC_CACHE)).thenReturn(false);
289 when(clusterService.createCache(RoutingTableImpl.GLOBALRPC_CACHE,
290 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
291 thenReturn(mockGlobalRpcCache);
293 when(clusterService.existCache(
294 RoutingTableImpl.RPC_CACHE)).thenReturn(false);
296 when(clusterService.createCache(RoutingTableImpl.RPC_CACHE,
297 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
298 thenReturn(mockRpcCache);
300 doNothing().when(clusterService).tbegin();
301 doNothing().when(clusterService).tcommit();
303 routingTable.setClusterGlobalServices(this.clusterService);
304 routingTable.init(c);
306 Assert.assertEquals(mockGlobalRpcCache, routingTable.getGlobalRpcCache());
307 Assert.assertEquals(mockRpcCache, routingTable.getRpcCache());
310 private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> getRouteIdentifier(){
311 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = mock(RpcRouter.RouteIdentifier.class);
312 InstanceIdentifier identifier = mock(InstanceIdentifier.class);
313 when(routeIdentifier.getType()).thenReturn(QNAME);
314 when(routeIdentifier.getRoute()).thenReturn(identifier);
316 return routeIdentifier;
319 private Runnable addRoutes(final int numRoutes, final String routePrefix, final RpcRouter.RouteIdentifier routeId){
320 return new Runnable() {
323 for (int i=0;i<numRoutes;i++){
324 String route = routePrefix + i;
326 routingTable.addRoute(routeId, route);
327 } catch (Exception e) {