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 junit.framework.Assert;
12 import org.apache.felix.dm.Component;
13 import org.junit.After;
14 import org.junit.Before;
15 import org.junit.Test;
16 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
17 import org.opendaylight.controller.clustering.services.IClusterServices;
18 import org.opendaylight.controller.sal.connector.api.RpcRouter;
19 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTable;
20 import org.opendaylight.controller.sal.connector.remoterpc.api.RoutingTableException;
21 import org.opendaylight.controller.sal.connector.remoterpc.api.SystemException;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
26 import java.util.EnumSet;
27 import java.util.HashSet;
28 import java.util.LinkedHashSet;
30 import java.util.concurrent.*;
32 import static org.mockito.Mockito.*;
34 public class RoutingTableImplTest {
36 private final URI namespace = URI.create("http://cisco.com/example");
37 private final QName QNAME = new QName(namespace, "global");
39 private IClusterGlobalServices clusterService;
40 private RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
41 ConcurrentMap mockGlobalRpcCache;
42 ConcurrentMap mockRpcCache;
45 public void setUp() throws Exception{
46 clusterService = mock(IClusterGlobalServices.class);
47 routingTable = new RoutingTableImpl<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
48 mockGlobalRpcCache = new ConcurrentHashMap<>();
49 mockRpcCache = new ConcurrentHashMap<>();
50 createRoutingTableCache();
54 public void tearDown(){
55 reset(clusterService);
56 mockGlobalRpcCache = null;
61 public void addGlobalRoute_ValidArguments_ShouldAdd() throws Exception {
63 Assert.assertNotNull(mockGlobalRpcCache);
64 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
66 final String expectedRoute = "172.27.12.1:5000";
67 routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
69 ConcurrentMap latestCache = routingTable.getGlobalRpcCache();
70 Assert.assertEquals(mockGlobalRpcCache, latestCache);
71 Assert.assertEquals(expectedRoute, latestCache.get(routeIdentifier));
74 @Test (expected = RoutingTable.DuplicateRouteException.class)
75 public void addGlobalRoute_DuplicateRoute_ShouldThrow() throws Exception{
77 Assert.assertNotNull(mockGlobalRpcCache);
79 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
80 routingTable.addGlobalRoute(routeIdentifier, new String());
81 routingTable.addGlobalRoute(routeIdentifier, new String());
85 public void getGlobalRoute_ExistingRouteId_ShouldReturnRoute() throws Exception {
87 Assert.assertNotNull(mockGlobalRpcCache);
88 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
89 String expectedRoute = "172.27.12.1:5000";
91 routingTable.addGlobalRoute(routeIdentifier, expectedRoute);
93 String actualRoute = (String) routingTable.getGlobalRoute(routeIdentifier);
94 Assert.assertEquals(expectedRoute, actualRoute);
98 public void getGlobalRoute_NonExistentRouteId_ShouldReturnNull() throws Exception {
100 Assert.assertNotNull(mockGlobalRpcCache);
101 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
103 String actualRoute = (String) routingTable.getGlobalRoute(routeIdentifier);
104 Assert.assertNull(actualRoute);
108 public void removeGlobalRoute_ExistingRouteId_ShouldRemove() throws Exception {
110 Assert.assertNotNull(mockGlobalRpcCache);
111 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
113 ConcurrentMap cache = routingTable.getGlobalRpcCache();
114 Assert.assertTrue(cache.size() == 0);
115 routingTable.addGlobalRoute(routeIdentifier, "172.27.12.1:5000");
116 Assert.assertTrue(cache.size() == 1);
118 routingTable.removeGlobalRoute(routeIdentifier);
119 Assert.assertTrue(cache.size() == 0);
124 public void removeGlobalRoute_NonExistentRouteId_ShouldDoNothing() throws Exception {
126 Assert.assertNotNull(mockGlobalRpcCache);
127 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = getRouteIdentifier();
129 ConcurrentMap cache = routingTable.getGlobalRpcCache();
130 Assert.assertTrue(cache.size() == 0);
132 routingTable.removeGlobalRoute(routeIdentifier);
133 Assert.assertTrue(cache.size() == 0);
138 public void addRoute_ForNewRouteId_ShouldAddRoute() throws Exception {
139 Assert.assertTrue(mockRpcCache.size() == 0);
141 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
143 routingTable.addRoute(routeId, new String());
144 Assert.assertTrue(mockRpcCache.size() == 1);
146 Set<String> routes = routingTable.getRoutes(routeId);
147 Assert.assertEquals(1, routes.size());
151 public void addRoute_ForExistingRouteId_ShouldAppendRoute() throws Exception {
153 Assert.assertTrue(mockRpcCache.size() == 0);
155 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeId = getRouteIdentifier();
157 String route_1 = "10.0.0.1:5955";
158 String route_2 = "10.0.0.2:5955";
160 routingTable.addRoute(routeId, route_1);
161 routingTable.addRoute(routeId, route_2);
163 Assert.assertTrue(mockRpcCache.size() == 1);
165 Set<String> routes = routingTable.getRoutes(routeId);
166 Assert.assertEquals(2, routes.size());
167 Assert.assertTrue(routes.contains(route_1));
168 Assert.assertTrue(routes.contains(route_2));
172 public void addRoute_UsingMultipleThreads_ShouldNotOverwrite(){
173 ExecutorService threadPool = Executors.newCachedThreadPool();
175 int numOfRoutesToAdd = 100;
176 String routePrefix_1 = "10.0.0.1:555";
177 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
178 threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_1, routeId));
179 String routePrefix_2 = "10.0.0.1:556";
180 threadPool.submit(addRoutes(numOfRoutesToAdd, routePrefix_2, routeId));
182 // wait for all tasks to complete; timeout in 10 sec
183 threadPool.shutdown();
185 threadPool.awaitTermination(10, TimeUnit.SECONDS); //
186 } catch (InterruptedException e) {
190 Assert.assertEquals(2*numOfRoutesToAdd, routingTable.getRoutes(routeId).size());
193 @Test(expected = NullPointerException.class)
194 public void addRoute_NullRouteId_shouldThrowNpe() throws Exception {
196 routingTable.addRoute(null, new String());
199 @Test(expected = NullPointerException.class)
200 public void addRoute_NullRoute_shouldThrowNpe() throws Exception{
202 routingTable.addRoute(getRouteIdentifier(), null);
205 @Test (expected = UnsupportedOperationException.class)
206 public void getRoutes_Call_ShouldReturnImmutableCopy() throws Exception{
207 Assert.assertNotNull(routingTable);
208 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
209 routingTable.addRoute(routeId, new String());
211 Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
213 routes.add(new String()); //can not be modified; should throw
217 public void getRoutes_With2RoutesFor1RouteId_ShouldReturnASetWithSize2() throws Exception{
218 Assert.assertNotNull(routingTable);
219 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
220 routingTable.addRoute(routeId, "10.0.0.1:5555");
221 routingTable.addRoute(routeId, "10.0.0.2:5555");
223 Set<String> routes = routingTable.getRoutes(routeId); //returns Immutable Set
225 Assert.assertEquals(2, routes.size());
229 public void getLastAddedRoute_WhenMultipleRoutesExists_ShouldReturnLatestRoute()
232 Assert.assertNotNull(routingTable);
233 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
234 String route_1 = "10.0.0.1:5555";
235 String route_2 = "10.0.0.2:5555";
236 routingTable.addRoute(routeId, route_1);
237 routingTable.addRoute(routeId, route_2);
239 Assert.assertEquals(route_2, routingTable.getLastAddedRoute(routeId));
243 public void removeRoute_WhenMultipleRoutesExist_RemovesGivenRoute() throws Exception{
244 Assert.assertNotNull(routingTable);
245 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
246 String route_1 = "10.0.0.1:5555";
247 String route_2 = "10.0.0.2:5555";
249 routingTable.addRoute(routeId, route_1);
250 routingTable.addRoute(routeId, route_2);
252 Assert.assertEquals(2, routingTable.getRoutes(routeId).size());
254 routingTable.removeRoute(routeId, route_1);
255 Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
260 public void removeRoute_WhenOnlyOneRouteExists_RemovesRouteId() throws Exception{
261 Assert.assertNotNull(routingTable);
262 RpcRouter.RouteIdentifier routeId = getRouteIdentifier();
263 String route_1 = "10.0.0.1:5555";
265 routingTable.addRoute(routeId, route_1);
266 Assert.assertEquals(1, routingTable.getRoutes(routeId).size());
268 routingTable.removeRoute(routeId, route_1);
269 ConcurrentMap cache = routingTable.getRpcCache();
270 Assert.assertFalse(cache.containsKey(routeId));
275 * Private helper methods
277 private void createRoutingTableCache() throws Exception {
280 Component c = mock(Component.class);
282 when(clusterService.existCache(
283 RoutingTableImpl.GLOBALRPC_CACHE)).thenReturn(false);
285 when(clusterService.createCache(RoutingTableImpl.GLOBALRPC_CACHE,
286 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
287 thenReturn(mockGlobalRpcCache);
289 when(clusterService.existCache(
290 RoutingTableImpl.RPC_CACHE)).thenReturn(false);
292 when(clusterService.createCache(RoutingTableImpl.RPC_CACHE,
293 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).
294 thenReturn(mockRpcCache);
296 doNothing().when(clusterService).tbegin();
297 doNothing().when(clusterService).tcommit();
299 routingTable.setClusterGlobalServices(this.clusterService);
300 routingTable.init(c);
302 Assert.assertEquals(mockGlobalRpcCache, routingTable.getGlobalRpcCache());
303 Assert.assertEquals(mockRpcCache, routingTable.getRpcCache());
306 private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> getRouteIdentifier(){
307 RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier = mock(RpcRouter.RouteIdentifier.class);
308 InstanceIdentifier identifier = mock(InstanceIdentifier.class);
309 when(routeIdentifier.getType()).thenReturn(QNAME);
310 when(routeIdentifier.getRoute()).thenReturn(identifier);
312 return routeIdentifier;
315 private Runnable addRoutes(final int numRoutes, final String routePrefix, final RpcRouter.RouteIdentifier routeId){
316 return new Runnable() {
319 for (int i=0;i<numRoutes;i++){
320 String route = routePrefix + i;
322 routingTable.addRoute(routeId, route);
323 } catch (Exception e) {