blob: 0f9d61e416c53cf5149abf2a7802a6fd27eb37c6 [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,
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070052 ZookeeperRegistry.SwitchPathCacheListener.class })
Naoki Shiotad00accf2013-06-25 14:40:37 -070053public class ZookeeperRegistryTest extends FloodlightTestCase {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070054 private static final 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;
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070060 protected static 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 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070066 @Override
Ray Milkey269ffb92014-04-03 14:43:30 -070067 @Before
68 public void setUp() throws Exception {
69 super.setUp();
Naoki Shiotad00accf2013-06-25 14:40:37 -070070
Ray Milkey269ffb92014-04-03 14:43:30 -070071 pathChildrenCacheListener = null;
Naoki Shiotad00accf2013-06-25 14:40:37 -070072
Ray Milkey269ffb92014-04-03 14:43:30 -070073 // Mock of CuratorFramework
74 client = createCuratorFrameworkMock();
Naoki Shiotad00accf2013-06-25 14:40:37 -070075
Ray Milkey269ffb92014-04-03 14:43:30 -070076 // Mock of CuratorFrameworkFactory
77 PowerMock.mockStatic(CuratorFrameworkFactory.class);
78 EasyMock.expect(CuratorFrameworkFactory.newClient((String) EasyMock.anyObject(),
79 EasyMock.anyInt(), EasyMock.anyInt(), (RetryPolicy) EasyMock.anyObject())).andReturn(client);
80 PowerMock.replay(CuratorFrameworkFactory.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -070081
Ray Milkey269ffb92014-04-03 14:43:30 -070082 FloodlightModuleContext fmc = new FloodlightModuleContext();
83 registry = new ZookeeperRegistry();
84 fmc.addService(ZookeeperRegistry.class, registry);
Naoki Shiotad00accf2013-06-25 14:40:37 -070085
Ray Milkey269ffb92014-04-03 14:43:30 -070086 registry.init(fmc);
Naoki Shiotad00accf2013-06-25 14:40:37 -070087
Ray Milkey269ffb92014-04-03 14:43:30 -070088 PowerMock.verify(client, CuratorFrameworkFactory.class);
89 }
Naoki Shiotad00accf2013-06-25 14:40:37 -070090
Ray Milkey269ffb92014-04-03 14:43:30 -070091 /**
92 * Clean up member variables (empty for now).
93 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070094 @Override
Ray Milkey269ffb92014-04-03 14:43:30 -070095 @After
96 public void tearDown() throws Exception {
97 super.tearDown();
98 }
Naoki Shiotad00accf2013-06-25 14:40:37 -070099
Ray Milkey269ffb92014-04-03 14:43:30 -0700100 /**
101 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
102 * (Exceptions are usually out of test target, but {@link ZookeeperRegistry#registerController(String)} throws an exception in case of invalid registration.)
103 */
104 @Test
105 public void testRegisterController() {
106 String controllerIdToRegister = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700107
Ray Milkey269ffb92014-04-03 14:43:30 -0700108 try {
109 registry.registerController(controllerIdToRegister);
110 } catch (RegistryException e) {
111 e.printStackTrace();
112 fail(e.getMessage());
113 }
114 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700115
Ray Milkey269ffb92014-04-03 14:43:30 -0700116 /**
117 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
118 *
119 * @throws Exception
120 */
121 @Test
122 public void testGetControllerId() throws Exception {
123 String controllerIdToRegister = "controller1";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700124
Ray Milkey269ffb92014-04-03 14:43:30 -0700125 // try before controller is registered
126 String controllerId = registry.getControllerId();
127 assertNull(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700128
Ray Milkey269ffb92014-04-03 14:43:30 -0700129 // register
130 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700131
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 // call getControllerId and verify
133 controllerId = registry.getControllerId();
134 assertNotNull(controllerId);
135 assertEquals(controllerIdToRegister, controllerId);
136 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700137
Ray Milkey269ffb92014-04-03 14:43:30 -0700138 /**
139 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
140 * Controllers to be returned are injected while setup. See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
141 * to what controllers are injected using mock {@link ServiceCache}.
142 *
143 * @throws Exception
144 */
145 @Test
146 public void testGetAllControllers() throws Exception {
147 String controllerIdRegistered = "controller1";
148 String controllerIdNotRegistered = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700149
Ray Milkey269ffb92014-04-03 14:43:30 -0700150 try {
151 Collection<String> ctrls = registry.getAllControllers();
152 assertTrue(ctrls.contains(controllerIdRegistered));
153 assertFalse(ctrls.contains(controllerIdNotRegistered));
154 } catch (RegistryException e) {
155 e.printStackTrace();
156 fail(e.getMessage());
157 }
158 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700159
Ray Milkey269ffb92014-04-03 14:43:30 -0700160 /**
161 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
162 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
163 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
164 *
165 * @throws Exception
166 */
167 @Test
168 public void testRequestControl() throws Exception {
169 // Mock LeaderLatch
170 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
171 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
172 EasyMock.expectLastCall().once();
173 latch.start();
174 EasyMock.expectLastCall().once();
175 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700176
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 PowerMock.expectNew(LeaderLatch.class,
178 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
179 .andReturn(latch).once();
180 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700181
Ray Milkey269ffb92014-04-03 14:43:30 -0700182 String controllerId = "controller2013";
183 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700184
Ray Milkey269ffb92014-04-03 14:43:30 -0700185 LoggingCallback callback = new LoggingCallback(1);
186 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700187
Ray Milkey269ffb92014-04-03 14:43:30 -0700188 try {
189 registry.requestControl(dpidToRequest, callback);
190 } catch (RegistryException e) {
191 e.printStackTrace();
192 fail(e.getMessage());
193 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700194
Ray Milkey269ffb92014-04-03 14:43:30 -0700195 EasyMock.verify(latch);
196 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700197
Ray Milkey269ffb92014-04-03 14:43:30 -0700198 /**
199 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
200 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
201 * {@link LeaderLatch} object and verify latch is correctly set up.
202 *
203 * @throws Exception
204 */
205 @Test
206 public void testReleaseControl() throws Exception {
207 // Mock of LeaderLatch
208 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
209 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
210 EasyMock.expectLastCall().once();
211 latch.start();
212 EasyMock.expectLastCall().once();
213 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
214 EasyMock.expectLastCall().once();
215 latch.close();
216 EasyMock.expectLastCall().once();
217 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700218
Ray Milkey269ffb92014-04-03 14:43:30 -0700219 PowerMock.expectNew(LeaderLatch.class,
220 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
221 .andReturn(latch).once();
222 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700223
Ray Milkey269ffb92014-04-03 14:43:30 -0700224 String controllerId = "controller2013";
225 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700226
Ray Milkey269ffb92014-04-03 14:43:30 -0700227 long dpidToRequest = 2000L;
228 LoggingCallback callback = new LoggingCallback(1);
229
230 registry.requestControl(dpidToRequest, callback);
231 registry.releaseControl(dpidToRequest);
232
233 EasyMock.verify(latch);
234 }
235
236 /**
237 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
238 *
239 * @throws Exception
240 */
241 @Test
242 public void testHasControl() throws Exception {
243 // Mock of LeaderLatch
244 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
245 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
246 EasyMock.expectLastCall().once();
247 latch.start();
248 EasyMock.expectLastCall().once();
249 EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
250 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
251 EasyMock.expectLastCall().once();
252 latch.close();
253 EasyMock.expectLastCall().once();
254 EasyMock.replay(latch);
255
256 PowerMock.expectNew(LeaderLatch.class,
257 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
258 .andReturn(latch);
259 PowerMock.replay(LeaderLatch.class);
260
261 String controllerId = "controller2013";
262 registry.registerController(controllerId);
263
264 long dpidToRequest = 2000L;
265 LoggingCallback callback = new LoggingCallback(2);
266
267 // Test before request control
268 assertFalse(registry.hasControl(dpidToRequest));
269
270 registry.requestControl(dpidToRequest, callback);
271
272 // Test after request control
273 assertTrue(registry.hasControl(dpidToRequest));
274
275 registry.releaseControl(dpidToRequest);
276
277 // Test after release control
278 assertFalse(registry.hasControl(dpidToRequest));
279
280 EasyMock.verify(latch);
281 }
282
283 /**
284 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)} correctly returns controller ID of specific switch.
285 * Relation between controllers and switches are defined by {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
286 *
287 * @throws Throwable
288 */
289 @Test
290 public void testGetControllerForSwitch() throws Throwable {
291 long dpidRegistered = 1000L;
292 long dpidNotRegistered = 2000L;
293
294 setPathChildrenCache();
295
296 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
297 assertEquals("controller1", controllerForSw);
298
299 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
300 assertEquals(null, controllerForSw);
301 }
302
303 /**
304 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
305 * switches controlled by a controller.
306 *
307 * @throws Exception
308 */
309 // TODO: Test after getSwitchesControlledByController() is implemented.
310 @Ignore
311 @Test
312 public void testGetSwitchesControlledByController() throws Exception {
313 String controllerIdRegistered = "controller1";
314 String dpidRegistered = HexString.toHexString(1000L);
315 String controllerIdNotRegistered = CONTROLLER_ID;
316
317 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
318 assertNotNull(switches);
319 assertTrue(switches.contains(dpidRegistered));
320
321 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
322 assertNotNull(switches);
323 assertEquals(0, switches.size());
324 }
325
326 /**
327 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
328 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
329 *
330 * @throws Exception
331 */
332 @Test
333 public void testGetAllSwitches() throws Exception {
334 String[] dpids = {
335 HexString.toHexString(1000L),
336 HexString.toHexString(1001L),
337 HexString.toHexString(1002L),
338 };
339
340 setPathChildrenCache();
341
342 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
343 assertNotNull(switches);
344 assertEquals(dpids.length, switches.size());
345 for (String dpid : dpids) {
346 assertTrue(switches.keySet().contains(dpid));
347 }
348 }
349
350 /**
351 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
352 */
353 @Test
354 public void testAllocateUniqueIdBlock() {
355 // Number of blocks to be verified that any of them has unique block
356 final int NUM_BLOCKS = 100;
357 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
358
359 for (int i = 0; i < NUM_BLOCKS; ++i) {
360 IdBlock block = registry.allocateUniqueIdBlock();
361 assertNotNull(block);
362 blocks.add(block);
363 }
364
365 for (int i = 0; i < NUM_BLOCKS; ++i) {
366 IdBlock block1 = blocks.get(i);
367 for (int j = i + 1; j < NUM_BLOCKS; ++j) {
368 IdBlock block2 = blocks.get(j);
369 IdBlock lower, higher;
370
371 if (block1.getStart() < block2.getStart()) {
372 lower = block1;
373 higher = block2;
374 } else {
375 lower = block2;
376 higher = block1;
377 }
378
379 assertTrue(lower.getSize() > 0L);
380 assertTrue(higher.getSize() > 0L);
381 assertTrue(lower.getEnd() <= higher.getStart());
382 }
383 }
384 }
385
386
387 //-------------------------- Creation of mock objects --------------------------
388
389 /**
390 * Create mock {@link CuratorFramework} object with initial value below.<br>
391 * [Ctrl ID] : [DPID]<br>
392 * controller1 : 1000<br>
393 * controller2 : 1001<br>
394 * controller2 : 1002<br>
395 * controller2013 : nothing
396 *
397 * @return Created mock object
398 * @throws Exception
399 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700400 @SuppressWarnings({"serial", "unchecked" })
Ray Milkey269ffb92014-04-03 14:43:30 -0700401 private CuratorFramework createCuratorFrameworkMock() throws Exception {
402 // Mock of AtomicValue
403 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
404 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
405 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
406 private long value = 0;
407
408 @Override
409 public Long answer() throws Throwable {
410 value += ID_BLOCK_SIZE;
411 return value;
412 }
413 }).anyTimes();
414 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
415 private long value = ID_BLOCK_SIZE;
416
417 @Override
418 public Long answer() throws Throwable {
419 value += ID_BLOCK_SIZE;
420 return value;
421 }
422 }).anyTimes();
423 EasyMock.replay(atomicValue);
424
425 // Mock DistributedAtomicLong
426 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
427 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
428 EasyMock.replay(daLong);
429 PowerMock.expectNew(DistributedAtomicLong.class,
430 new Class<?>[]{CuratorFramework.class, String.class, RetryPolicy.class},
431 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
432 andReturn(daLong).anyTimes();
433 PowerMock.replay(DistributedAtomicLong.class);
434
435 // Mock ListenerContainer
436 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
437 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
438 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
439 @Override
440 public Object answer() throws Throwable {
441 pathChildrenCacheListener = (PathChildrenCacheListener) EasyMock.getCurrentArguments()[0];
442 return null;
443 }
444 }).once();
445 EasyMock.replay(listenerContainer);
446
447 // Mock PathChildrenCache
448 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[]{"/switches"}, listenerContainer);
449 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[]{HexString.toHexString(1000L)}, listenerContainer);
450 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[]{
451 HexString.toHexString(1001L), HexString.toHexString(1002L)}, listenerContainer);
452
453 // Mock PathChildrenCache constructor
454 PowerMock.expectNew(PathChildrenCache.class,
455 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
456 andReturn(pathChildrenCacheMain).once();
457 PowerMock.expectNew(PathChildrenCache.class,
458 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
459 andReturn(pathChildrenCache1).once();
460 PowerMock.expectNew(PathChildrenCache.class,
461 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
462 andReturn(pathChildrenCache2).anyTimes();
463 PowerMock.replay(PathChildrenCache.class);
464
465 // Mock ServiceCache
466 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
467 serviceCache.start();
468 EasyMock.expectLastCall().once();
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700469 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService>>() { {
Ray Milkey269ffb92014-04-03 14:43:30 -0700470 add(createServiceInstanceMock("controller1"));
471 add(createServiceInstanceMock("controller2"));
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700472 } }).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700473 EasyMock.replay(serviceCache);
474
475 // Mock ServiceCacheBuilder
476 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
477 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
478 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
479 EasyMock.replay(serviceCacheBuilder);
480
481 // Mock ServiceDiscovery
482 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
483 serviceDiscovery.start();
484 EasyMock.expectLastCall().once();
485 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
486 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
487 EasyMock.expectLastCall().once();
488 EasyMock.replay(serviceDiscovery);
489
490 // Mock CuratorFramework
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700491 CuratorFramework mockClient = EasyMock.createMock(CuratorFramework.class);
492 mockClient.start();
Ray Milkey269ffb92014-04-03 14:43:30 -0700493 EasyMock.expectLastCall().once();
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700494 EasyMock.expect(mockClient.usingNamespace(EasyMock.anyObject(String.class))).andReturn(mockClient);
495 EasyMock.replay(mockClient);
Ray Milkey269ffb92014-04-03 14:43:30 -0700496
497 // Mock ServiceDiscoveryBuilder
498 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700499 EasyMock.expect(builder.client(mockClient)).andReturn(builder).once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700500 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
501 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
502 EasyMock.replay(builder);
503
504 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
505 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
506 PowerMock.replay(ServiceDiscoveryBuilder.class);
507
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700508 return mockClient;
Ray Milkey269ffb92014-04-03 14:43:30 -0700509 }
510
511 /**
512 * Create mock {@link ServiceInstance} object using given controller ID.
513 *
514 * @param controllerId Controller ID to represent instance's payload (ControllerService).
515 * @return Mock ServiceInstance object
516 */
517 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
518 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
519 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
520 EasyMock.replay(controllerService);
521
522 @SuppressWarnings("unchecked")
523 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
524 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
525 EasyMock.replay(serviceInstance);
526
527 return serviceInstance;
528 }
529
530 /**
531 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
532 *
533 * @param controllerId Controller ID to represent current data.
534 * @param paths List of HexString indicating switch's DPID.
535 * @param listener Callback object to be set as Listenable.
536 * @return Mock PathChildrenCache object
537 * @throws Exception
538 */
539 private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String[] paths,
540 ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
541 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
542
543 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
544
545 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
546 EasyMock.expectLastCall().anyTimes();
547
548 List<ChildData> childs = new ArrayList<ChildData>();
549 for (String path : paths) {
550 childs.add(createChildDataMockForCurrentData(controllerId, path));
551 }
552 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
553
554 pathChildrenCache.rebuild();
555 EasyMock.expectLastCall().anyTimes();
556
557 EasyMock.replay(pathChildrenCache);
558
559 return pathChildrenCache;
560 }
561
562 /**
563 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
564 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
565 *
566 * @param controllerId Controller ID
567 * @param path HexString indicating switch's DPID
568 * @return Mock ChildData object
569 */
570 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
571 ChildData data = EasyMock.createMock(ChildData.class);
572 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
573 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
574 EasyMock.replay(data);
575
576 return data;
577 }
578
579 /**
580 * Inject relations between controllers and switches using callback object.
581 *
582 * @throws Exception
583 */
584 private void setPathChildrenCache() throws Exception {
585 pathChildrenCacheListener.childEvent(client,
586 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
587 pathChildrenCacheListener.childEvent(client,
588 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
589 pathChildrenCacheListener.childEvent(client,
590 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
591 }
592
593 /**
594 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
595 *
596 * @param controllerId Controller ID.
597 * @param path HexString of DPID.
598 * @param type Event type to be set to mock object.
599 * @return Mock PathChildrenCacheEvent object
600 */
601 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
602 PathChildrenCacheEvent.Type type) {
603 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
604 ChildData data = EasyMock.createMock(ChildData.class);
605
606 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
607 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
608 EasyMock.replay(data);
609
610 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
611 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
612 EasyMock.replay(event);
613
614 return event;
615 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700616}