blob: 8275a84a817989db4dc86ef0e8192460bf237892 [file] [log] [blame]
Jonathan Hartdeda0ba2014-04-03 11:14:12 -07001package net.onrc.onos.core.registry;
Naoki Shiotad00accf2013-06-25 14:40:37 -07002
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.List;
6import java.util.Map;
7
8import net.floodlightcontroller.core.module.FloodlightModuleContext;
9import net.floodlightcontroller.test.FloodlightTestCase;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070010import net.onrc.onos.core.registry.StandaloneRegistryTest.LoggingCallback;
11import net.onrc.onos.core.registry.ZookeeperRegistry.SwitchLeaderListener;
Naoki Shiotad00accf2013-06-25 14:40:37 -070012
Jonathan Hart116b1fe2014-03-14 18:53:47 -070013import org.apache.curator.RetryPolicy;
14import org.apache.curator.framework.CuratorFramework;
15import org.apache.curator.framework.CuratorFrameworkFactory;
16import org.apache.curator.framework.listen.ListenerContainer;
17import org.apache.curator.framework.recipes.atomic.AtomicValue;
18import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
19import org.apache.curator.framework.recipes.cache.ChildData;
20import org.apache.curator.framework.recipes.cache.PathChildrenCache;
21import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
22import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
23import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
24import org.apache.curator.framework.recipes.leader.LeaderLatch;
25import org.apache.curator.x.discovery.ServiceCache;
26import org.apache.curator.x.discovery.ServiceCacheBuilder;
27import org.apache.curator.x.discovery.ServiceDiscovery;
28import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
29import org.apache.curator.x.discovery.ServiceInstance;
Naoki Shiotad00accf2013-06-25 14:40:37 -070030import org.easymock.EasyMock;
31import org.easymock.IAnswer;
32import org.junit.After;
33import org.junit.Before;
34import org.junit.Ignore;
35import org.junit.Test;
36import org.junit.runner.RunWith;
37import org.openflow.util.HexString;
38import org.powermock.api.easymock.PowerMock;
39import org.powermock.core.classloader.annotations.PrepareForTest;
40import org.powermock.modules.junit4.PowerMockRunner;
41
Naoki Shiotad00accf2013-06-25 14:40:37 -070042/**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070043 * Unit test for {@link ZookeeperRegistry}.
44 * NOTE: {@link FloodlightTestCase} conflicts with PowerMock. If FloodLight-related methods need to be tested,
Ray Milkey269ffb92014-04-03 14:43:30 -070045 * implement another test class to test them.
Naoki Shiotad00accf2013-06-25 14:40:37 -070046 *
Ray Milkey269ffb92014-04-03 14:43:30 -070047 * @author Naoki Shiota
Naoki Shiotad00accf2013-06-25 14:40:37 -070048 */
49@RunWith(PowerMockRunner.class)
50@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
Ray Milkey269ffb92014-04-03 14:43:30 -070051 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
52 ZookeeperRegistry.SwitchPathCacheListener.class})
Naoki Shiotad00accf2013-06-25 14:40:37 -070053public class ZookeeperRegistryTest extends FloodlightTestCase {
Ray Milkey269ffb92014-04-03 14:43:30 -070054 private final static Long ID_BLOCK_SIZE = 0x100000000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -070055
Ray Milkey269ffb92014-04-03 14:43:30 -070056 protected ZookeeperRegistry registry;
57 protected CuratorFramework client;
Naoki Shiotad00accf2013-06-25 14:40:37 -070058
Ray Milkey269ffb92014-04-03 14:43:30 -070059 protected PathChildrenCacheListener pathChildrenCacheListener;
60 protected final String CONTROLLER_ID = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -070061
Ray Milkey269ffb92014-04-03 14:43:30 -070062 /**
63 * Initialize {@link ZookeeperRegistry} Object and inject initial value with {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
64 * This setup code also tests {@link ZookeeperRegistry#init(FloodlightModuleContext)} method itself.
65 */
66 @Before
67 public void setUp() throws Exception {
68 super.setUp();
Naoki Shiotad00accf2013-06-25 14:40:37 -070069
Ray Milkey269ffb92014-04-03 14:43:30 -070070 pathChildrenCacheListener = null;
Naoki Shiotad00accf2013-06-25 14:40:37 -070071
Ray Milkey269ffb92014-04-03 14:43:30 -070072 // Mock of CuratorFramework
73 client = createCuratorFrameworkMock();
Naoki Shiotad00accf2013-06-25 14:40:37 -070074
Ray Milkey269ffb92014-04-03 14:43:30 -070075 // Mock of CuratorFrameworkFactory
76 PowerMock.mockStatic(CuratorFrameworkFactory.class);
77 EasyMock.expect(CuratorFrameworkFactory.newClient((String) EasyMock.anyObject(),
78 EasyMock.anyInt(), EasyMock.anyInt(), (RetryPolicy) EasyMock.anyObject())).andReturn(client);
79 PowerMock.replay(CuratorFrameworkFactory.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -070080
Ray Milkey269ffb92014-04-03 14:43:30 -070081 FloodlightModuleContext fmc = new FloodlightModuleContext();
82 registry = new ZookeeperRegistry();
83 fmc.addService(ZookeeperRegistry.class, registry);
Naoki Shiotad00accf2013-06-25 14:40:37 -070084
Ray Milkey269ffb92014-04-03 14:43:30 -070085 registry.init(fmc);
Naoki Shiotad00accf2013-06-25 14:40:37 -070086
Ray Milkey269ffb92014-04-03 14:43:30 -070087 PowerMock.verify(client, CuratorFrameworkFactory.class);
88 }
Naoki Shiotad00accf2013-06-25 14:40:37 -070089
Ray Milkey269ffb92014-04-03 14:43:30 -070090 /**
91 * Clean up member variables (empty for now).
92 */
93 @After
94 public void tearDown() throws Exception {
95 super.tearDown();
96 }
Naoki Shiotad00accf2013-06-25 14:40:37 -070097
Ray Milkey269ffb92014-04-03 14:43:30 -070098 /**
99 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
100 * (Exceptions are usually out of test target, but {@link ZookeeperRegistry#registerController(String)} throws an exception in case of invalid registration.)
101 */
102 @Test
103 public void testRegisterController() {
104 String controllerIdToRegister = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700105
Ray Milkey269ffb92014-04-03 14:43:30 -0700106 try {
107 registry.registerController(controllerIdToRegister);
108 } catch (RegistryException e) {
109 e.printStackTrace();
110 fail(e.getMessage());
111 }
112 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700113
Ray Milkey269ffb92014-04-03 14:43:30 -0700114 /**
115 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
116 *
117 * @throws Exception
118 */
119 @Test
120 public void testGetControllerId() throws Exception {
121 String controllerIdToRegister = "controller1";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700122
Ray Milkey269ffb92014-04-03 14:43:30 -0700123 // try before controller is registered
124 String controllerId = registry.getControllerId();
125 assertNull(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700126
Ray Milkey269ffb92014-04-03 14:43:30 -0700127 // register
128 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700129
Ray Milkey269ffb92014-04-03 14:43:30 -0700130 // call getControllerId and verify
131 controllerId = registry.getControllerId();
132 assertNotNull(controllerId);
133 assertEquals(controllerIdToRegister, controllerId);
134 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700135
Ray Milkey269ffb92014-04-03 14:43:30 -0700136 /**
137 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
138 * Controllers to be returned are injected while setup. See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
139 * to what controllers are injected using mock {@link ServiceCache}.
140 *
141 * @throws Exception
142 */
143 @Test
144 public void testGetAllControllers() throws Exception {
145 String controllerIdRegistered = "controller1";
146 String controllerIdNotRegistered = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700147
Ray Milkey269ffb92014-04-03 14:43:30 -0700148 try {
149 Collection<String> ctrls = registry.getAllControllers();
150 assertTrue(ctrls.contains(controllerIdRegistered));
151 assertFalse(ctrls.contains(controllerIdNotRegistered));
152 } catch (RegistryException e) {
153 e.printStackTrace();
154 fail(e.getMessage());
155 }
156 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700157
Ray Milkey269ffb92014-04-03 14:43:30 -0700158 /**
159 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
160 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
161 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
162 *
163 * @throws Exception
164 */
165 @Test
166 public void testRequestControl() throws Exception {
167 // Mock LeaderLatch
168 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
169 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
170 EasyMock.expectLastCall().once();
171 latch.start();
172 EasyMock.expectLastCall().once();
173 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700174
Ray Milkey269ffb92014-04-03 14:43:30 -0700175 PowerMock.expectNew(LeaderLatch.class,
176 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
177 .andReturn(latch).once();
178 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700179
Ray Milkey269ffb92014-04-03 14:43:30 -0700180 String controllerId = "controller2013";
181 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700182
Ray Milkey269ffb92014-04-03 14:43:30 -0700183 LoggingCallback callback = new LoggingCallback(1);
184 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700185
Ray Milkey269ffb92014-04-03 14:43:30 -0700186 try {
187 registry.requestControl(dpidToRequest, callback);
188 } catch (RegistryException e) {
189 e.printStackTrace();
190 fail(e.getMessage());
191 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700192
Ray Milkey269ffb92014-04-03 14:43:30 -0700193 EasyMock.verify(latch);
194 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700195
Ray Milkey269ffb92014-04-03 14:43:30 -0700196 /**
197 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
198 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
199 * {@link LeaderLatch} object and verify latch is correctly set up.
200 *
201 * @throws Exception
202 */
203 @Test
204 public void testReleaseControl() throws Exception {
205 // Mock of LeaderLatch
206 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
207 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
208 EasyMock.expectLastCall().once();
209 latch.start();
210 EasyMock.expectLastCall().once();
211 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
212 EasyMock.expectLastCall().once();
213 latch.close();
214 EasyMock.expectLastCall().once();
215 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700216
Ray Milkey269ffb92014-04-03 14:43:30 -0700217 PowerMock.expectNew(LeaderLatch.class,
218 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
219 .andReturn(latch).once();
220 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700221
Ray Milkey269ffb92014-04-03 14:43:30 -0700222 String controllerId = "controller2013";
223 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700224
Ray Milkey269ffb92014-04-03 14:43:30 -0700225 long dpidToRequest = 2000L;
226 LoggingCallback callback = new LoggingCallback(1);
227
228 registry.requestControl(dpidToRequest, callback);
229 registry.releaseControl(dpidToRequest);
230
231 EasyMock.verify(latch);
232 }
233
234 /**
235 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
236 *
237 * @throws Exception
238 */
239 @Test
240 public void testHasControl() throws Exception {
241 // Mock of LeaderLatch
242 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
243 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
244 EasyMock.expectLastCall().once();
245 latch.start();
246 EasyMock.expectLastCall().once();
247 EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
248 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
249 EasyMock.expectLastCall().once();
250 latch.close();
251 EasyMock.expectLastCall().once();
252 EasyMock.replay(latch);
253
254 PowerMock.expectNew(LeaderLatch.class,
255 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
256 .andReturn(latch);
257 PowerMock.replay(LeaderLatch.class);
258
259 String controllerId = "controller2013";
260 registry.registerController(controllerId);
261
262 long dpidToRequest = 2000L;
263 LoggingCallback callback = new LoggingCallback(2);
264
265 // Test before request control
266 assertFalse(registry.hasControl(dpidToRequest));
267
268 registry.requestControl(dpidToRequest, callback);
269
270 // Test after request control
271 assertTrue(registry.hasControl(dpidToRequest));
272
273 registry.releaseControl(dpidToRequest);
274
275 // Test after release control
276 assertFalse(registry.hasControl(dpidToRequest));
277
278 EasyMock.verify(latch);
279 }
280
281 /**
282 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)} correctly returns controller ID of specific switch.
283 * Relation between controllers and switches are defined by {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
284 *
285 * @throws Throwable
286 */
287 @Test
288 public void testGetControllerForSwitch() throws Throwable {
289 long dpidRegistered = 1000L;
290 long dpidNotRegistered = 2000L;
291
292 setPathChildrenCache();
293
294 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
295 assertEquals("controller1", controllerForSw);
296
297 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
298 assertEquals(null, controllerForSw);
299 }
300
301 /**
302 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
303 * switches controlled by a controller.
304 *
305 * @throws Exception
306 */
307 // TODO: Test after getSwitchesControlledByController() is implemented.
308 @Ignore
309 @Test
310 public void testGetSwitchesControlledByController() throws Exception {
311 String controllerIdRegistered = "controller1";
312 String dpidRegistered = HexString.toHexString(1000L);
313 String controllerIdNotRegistered = CONTROLLER_ID;
314
315 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
316 assertNotNull(switches);
317 assertTrue(switches.contains(dpidRegistered));
318
319 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
320 assertNotNull(switches);
321 assertEquals(0, switches.size());
322 }
323
324 /**
325 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
326 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
327 *
328 * @throws Exception
329 */
330 @Test
331 public void testGetAllSwitches() throws Exception {
332 String[] dpids = {
333 HexString.toHexString(1000L),
334 HexString.toHexString(1001L),
335 HexString.toHexString(1002L),
336 };
337
338 setPathChildrenCache();
339
340 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
341 assertNotNull(switches);
342 assertEquals(dpids.length, switches.size());
343 for (String dpid : dpids) {
344 assertTrue(switches.keySet().contains(dpid));
345 }
346 }
347
348 /**
349 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
350 */
351 @Test
352 public void testAllocateUniqueIdBlock() {
353 // Number of blocks to be verified that any of them has unique block
354 final int NUM_BLOCKS = 100;
355 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
356
357 for (int i = 0; i < NUM_BLOCKS; ++i) {
358 IdBlock block = registry.allocateUniqueIdBlock();
359 assertNotNull(block);
360 blocks.add(block);
361 }
362
363 for (int i = 0; i < NUM_BLOCKS; ++i) {
364 IdBlock block1 = blocks.get(i);
365 for (int j = i + 1; j < NUM_BLOCKS; ++j) {
366 IdBlock block2 = blocks.get(j);
367 IdBlock lower, higher;
368
369 if (block1.getStart() < block2.getStart()) {
370 lower = block1;
371 higher = block2;
372 } else {
373 lower = block2;
374 higher = block1;
375 }
376
377 assertTrue(lower.getSize() > 0L);
378 assertTrue(higher.getSize() > 0L);
379 assertTrue(lower.getEnd() <= higher.getStart());
380 }
381 }
382 }
383
384
385 //-------------------------- Creation of mock objects --------------------------
386
387 /**
388 * Create mock {@link CuratorFramework} object with initial value below.<br>
389 * [Ctrl ID] : [DPID]<br>
390 * controller1 : 1000<br>
391 * controller2 : 1001<br>
392 * controller2 : 1002<br>
393 * controller2013 : nothing
394 *
395 * @return Created mock object
396 * @throws Exception
397 */
398 @SuppressWarnings({"serial", "unchecked"})
399 private CuratorFramework createCuratorFrameworkMock() throws Exception {
400 // Mock of AtomicValue
401 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
402 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
403 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
404 private long value = 0;
405
406 @Override
407 public Long answer() throws Throwable {
408 value += ID_BLOCK_SIZE;
409 return value;
410 }
411 }).anyTimes();
412 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
413 private long value = ID_BLOCK_SIZE;
414
415 @Override
416 public Long answer() throws Throwable {
417 value += ID_BLOCK_SIZE;
418 return value;
419 }
420 }).anyTimes();
421 EasyMock.replay(atomicValue);
422
423 // Mock DistributedAtomicLong
424 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
425 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
426 EasyMock.replay(daLong);
427 PowerMock.expectNew(DistributedAtomicLong.class,
428 new Class<?>[]{CuratorFramework.class, String.class, RetryPolicy.class},
429 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
430 andReturn(daLong).anyTimes();
431 PowerMock.replay(DistributedAtomicLong.class);
432
433 // Mock ListenerContainer
434 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
435 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
436 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
437 @Override
438 public Object answer() throws Throwable {
439 pathChildrenCacheListener = (PathChildrenCacheListener) EasyMock.getCurrentArguments()[0];
440 return null;
441 }
442 }).once();
443 EasyMock.replay(listenerContainer);
444
445 // Mock PathChildrenCache
446 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[]{"/switches"}, listenerContainer);
447 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[]{HexString.toHexString(1000L)}, listenerContainer);
448 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[]{
449 HexString.toHexString(1001L), HexString.toHexString(1002L)}, listenerContainer);
450
451 // Mock PathChildrenCache constructor
452 PowerMock.expectNew(PathChildrenCache.class,
453 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
454 andReturn(pathChildrenCacheMain).once();
455 PowerMock.expectNew(PathChildrenCache.class,
456 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
457 andReturn(pathChildrenCache1).once();
458 PowerMock.expectNew(PathChildrenCache.class,
459 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
460 andReturn(pathChildrenCache2).anyTimes();
461 PowerMock.replay(PathChildrenCache.class);
462
463 // Mock ServiceCache
464 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
465 serviceCache.start();
466 EasyMock.expectLastCall().once();
467 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService>>() {{
468 add(createServiceInstanceMock("controller1"));
469 add(createServiceInstanceMock("controller2"));
470 }}).anyTimes();
471 EasyMock.replay(serviceCache);
472
473 // Mock ServiceCacheBuilder
474 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
475 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
476 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
477 EasyMock.replay(serviceCacheBuilder);
478
479 // Mock ServiceDiscovery
480 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
481 serviceDiscovery.start();
482 EasyMock.expectLastCall().once();
483 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
484 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
485 EasyMock.expectLastCall().once();
486 EasyMock.replay(serviceDiscovery);
487
488 // Mock CuratorFramework
489 CuratorFramework client = EasyMock.createMock(CuratorFramework.class);
490 client.start();
491 EasyMock.expectLastCall().once();
492 EasyMock.expect(client.usingNamespace(EasyMock.anyObject(String.class))).andReturn(client);
493 EasyMock.replay(client);
494
495 // Mock ServiceDiscoveryBuilder
496 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
497 EasyMock.expect(builder.client(client)).andReturn(builder).once();
498 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
499 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
500 EasyMock.replay(builder);
501
502 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
503 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
504 PowerMock.replay(ServiceDiscoveryBuilder.class);
505
506 return client;
507 }
508
509 /**
510 * Create mock {@link ServiceInstance} object using given controller ID.
511 *
512 * @param controllerId Controller ID to represent instance's payload (ControllerService).
513 * @return Mock ServiceInstance object
514 */
515 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
516 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
517 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
518 EasyMock.replay(controllerService);
519
520 @SuppressWarnings("unchecked")
521 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
522 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
523 EasyMock.replay(serviceInstance);
524
525 return serviceInstance;
526 }
527
528 /**
529 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
530 *
531 * @param controllerId Controller ID to represent current data.
532 * @param paths List of HexString indicating switch's DPID.
533 * @param listener Callback object to be set as Listenable.
534 * @return Mock PathChildrenCache object
535 * @throws Exception
536 */
537 private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String[] paths,
538 ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
539 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
540
541 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
542
543 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
544 EasyMock.expectLastCall().anyTimes();
545
546 List<ChildData> childs = new ArrayList<ChildData>();
547 for (String path : paths) {
548 childs.add(createChildDataMockForCurrentData(controllerId, path));
549 }
550 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
551
552 pathChildrenCache.rebuild();
553 EasyMock.expectLastCall().anyTimes();
554
555 EasyMock.replay(pathChildrenCache);
556
557 return pathChildrenCache;
558 }
559
560 /**
561 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
562 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
563 *
564 * @param controllerId Controller ID
565 * @param path HexString indicating switch's DPID
566 * @return Mock ChildData object
567 */
568 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
569 ChildData data = EasyMock.createMock(ChildData.class);
570 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
571 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
572 EasyMock.replay(data);
573
574 return data;
575 }
576
577 /**
578 * Inject relations between controllers and switches using callback object.
579 *
580 * @throws Exception
581 */
582 private void setPathChildrenCache() throws Exception {
583 pathChildrenCacheListener.childEvent(client,
584 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
585 pathChildrenCacheListener.childEvent(client,
586 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
587 pathChildrenCacheListener.childEvent(client,
588 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
589 }
590
591 /**
592 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
593 *
594 * @param controllerId Controller ID.
595 * @param path HexString of DPID.
596 * @param type Event type to be set to mock object.
597 * @return Mock PathChildrenCacheEvent object
598 */
599 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
600 PathChildrenCacheEvent.Type type) {
601 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
602 ChildData data = EasyMock.createMock(ChildData.class);
603
604 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
605 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
606 EasyMock.replay(data);
607
608 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
609 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
610 EasyMock.replay(event);
611
612 return event;
613 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700614}