blob: 06de77e0a55bc932551060f271073d2fb02d1e00 [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.ControllerRegistryEntry;
11import net.onrc.onos.core.registry.ControllerService;
12import net.onrc.onos.core.registry.IdBlock;
13import net.onrc.onos.core.registry.RegistryException;
14import net.onrc.onos.core.registry.ZookeeperRegistry;
15import net.onrc.onos.core.registry.StandaloneRegistryTest.LoggingCallback;
16import net.onrc.onos.core.registry.ZookeeperRegistry.SwitchLeaderListener;
Naoki Shiotad00accf2013-06-25 14:40:37 -070017
Jonathan Hart116b1fe2014-03-14 18:53:47 -070018import org.apache.curator.RetryPolicy;
19import org.apache.curator.framework.CuratorFramework;
20import org.apache.curator.framework.CuratorFrameworkFactory;
21import org.apache.curator.framework.listen.ListenerContainer;
22import org.apache.curator.framework.recipes.atomic.AtomicValue;
23import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
24import org.apache.curator.framework.recipes.cache.ChildData;
25import org.apache.curator.framework.recipes.cache.PathChildrenCache;
26import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
27import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
28import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
29import org.apache.curator.framework.recipes.leader.LeaderLatch;
30import org.apache.curator.x.discovery.ServiceCache;
31import org.apache.curator.x.discovery.ServiceCacheBuilder;
32import org.apache.curator.x.discovery.ServiceDiscovery;
33import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
34import org.apache.curator.x.discovery.ServiceInstance;
Naoki Shiotad00accf2013-06-25 14:40:37 -070035import org.easymock.EasyMock;
36import org.easymock.IAnswer;
37import org.junit.After;
38import org.junit.Before;
39import org.junit.Ignore;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42import org.openflow.util.HexString;
43import org.powermock.api.easymock.PowerMock;
44import org.powermock.core.classloader.annotations.PrepareForTest;
45import org.powermock.modules.junit4.PowerMockRunner;
46
Naoki Shiotad00accf2013-06-25 14:40:37 -070047/**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070048 * Unit test for {@link ZookeeperRegistry}.
49 * NOTE: {@link FloodlightTestCase} conflicts with PowerMock. If FloodLight-related methods need to be tested,
Naoki Shiotad00accf2013-06-25 14:40:37 -070050 * implement another test class to test them.
51 * @author Naoki Shiota
52 *
53 */
54@RunWith(PowerMockRunner.class)
55@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
56 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
57 ZookeeperRegistry.SwitchPathCacheListener.class})
58public class ZookeeperRegistryTest extends FloodlightTestCase {
59 private final static Long ID_BLOCK_SIZE = 0x100000000L;
60
61 protected ZookeeperRegistry registry;
62 protected CuratorFramework client;
63
64 protected PathChildrenCacheListener pathChildrenCacheListener;
65 protected final String CONTROLLER_ID = "controller2013";
66
67 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070068 * Initialize {@link ZookeeperRegistry} Object and inject initial value with {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
69 * This setup code also tests {@link ZookeeperRegistry#init(FloodlightModuleContext)} method itself.
Naoki Shiotad00accf2013-06-25 14:40:37 -070070 */
71 @Before
72 public void setUp() throws Exception {
73 super.setUp();
74
75 pathChildrenCacheListener = null;
76
77 // Mock of CuratorFramework
78 client = createCuratorFrameworkMock();
79
80 // Mock of CuratorFrameworkFactory
81 PowerMock.mockStatic(CuratorFrameworkFactory.class);
82 EasyMock.expect(CuratorFrameworkFactory.newClient((String)EasyMock.anyObject(),
83 EasyMock.anyInt(), EasyMock.anyInt(), (RetryPolicy)EasyMock.anyObject())).andReturn(client);
84 PowerMock.replay(CuratorFrameworkFactory.class);
85
86 FloodlightModuleContext fmc = new FloodlightModuleContext();
87 registry = new ZookeeperRegistry();
88 fmc.addService(ZookeeperRegistry.class, registry);
89
90 registry.init(fmc);
91
92 PowerMock.verify(client, CuratorFrameworkFactory.class);
93 }
94
95 /**
96 * Clean up member variables (empty for now).
97 */
98 @After
99 public void tearDown() throws Exception {
100 super.tearDown();
101 }
102
103 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700104 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
105 * (Exceptions are usually out of test target, but {@link ZookeeperRegistry#registerController(String)} throws an exception in case of invalid registration.)
Naoki Shiotad00accf2013-06-25 14:40:37 -0700106 */
107 @Test
108 public void testRegisterController() {
109 String controllerIdToRegister = "controller2013";
110
111 try {
112 registry.registerController(controllerIdToRegister);
113 } catch (RegistryException e) {
114 e.printStackTrace();
115 fail(e.getMessage());
116 }
117 }
118
119 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700120 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700121 * @throws Exception
122 */
123 @Test
124 public void testGetControllerId() throws Exception {
125 String controllerIdToRegister = "controller1";
126
127 // try before controller is registered
128 String controllerId = registry.getControllerId();
129 assertNull(controllerId);
130
131 // register
132 registry.registerController(controllerIdToRegister);
133
134 // call getControllerId and verify
135 controllerId = registry.getControllerId();
136 assertNotNull(controllerId);
137 assertEquals(controllerIdToRegister, controllerId);
138 }
139
140 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700141 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
142 * Controllers to be returned are injected while setup. See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
143 * to what controllers are injected using mock {@link ServiceCache}.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700144 * @throws Exception
145 */
146 @Test
147 public void testGetAllControllers() throws Exception {
148 String controllerIdRegistered = "controller1";
149 String controllerIdNotRegistered = "controller2013";
150
Naoki Shiotad00accf2013-06-25 14:40:37 -0700151 try {
152 Collection<String> ctrls = registry.getAllControllers();
153 assertTrue(ctrls.contains(controllerIdRegistered));
154 assertFalse(ctrls.contains(controllerIdNotRegistered));
155 } catch (RegistryException e) {
156 e.printStackTrace();
157 fail(e.getMessage());
158 }
159 }
160
161 /**
Jonathan Hartdeda0ba2014-04-03 11:14:12 -0700162 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
163 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback)}
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700164 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700165 * @throws Exception
166 */
167 @Test
168 public void testRequestControl() throws Exception {
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700169 // Mock LeaderLatch
Naoki Shiotad00accf2013-06-25 14:40:37 -0700170 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);
176
177 PowerMock.expectNew(LeaderLatch.class,
178 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700179 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700180 PowerMock.replay(LeaderLatch.class);
181
182 String controllerId = "controller2013";
183 registry.registerController(controllerId);
184
185 LoggingCallback callback = new LoggingCallback(1);
186 long dpidToRequest = 2000L;
187
188 try {
189 registry.requestControl(dpidToRequest, callback);
190 } catch (RegistryException e) {
191 e.printStackTrace();
192 fail(e.getMessage());
193 }
194
195 EasyMock.verify(latch);
196 }
197
198 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700199 * 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.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700202 * @throws Exception
203 */
204 @Test
205 public void testReleaseControl() throws Exception {
206 // Mock of LeaderLatch
207 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
208 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
209 EasyMock.expectLastCall().once();
210 latch.start();
211 EasyMock.expectLastCall().once();
Jonathan Hart116b1fe2014-03-14 18:53:47 -0700212 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700213 EasyMock.expectLastCall().once();
214 latch.close();
215 EasyMock.expectLastCall().once();
216 EasyMock.replay(latch);
217
218 PowerMock.expectNew(LeaderLatch.class,
219 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700220 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700221 PowerMock.replay(LeaderLatch.class);
222
223 String controllerId = "controller2013";
224 registry.registerController(controllerId);
225
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700226 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700227 LoggingCallback callback = new LoggingCallback(1);
228
Naoki Shiotad00accf2013-06-25 14:40:37 -0700229 registry.requestControl(dpidToRequest, callback);
230 registry.releaseControl(dpidToRequest);
231
Naoki Shiotad00accf2013-06-25 14:40:37 -0700232 EasyMock.verify(latch);
233 }
234
235 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700236 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700237 * @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();
Jonathan Hart116b1fe2014-03-14 18:53:47 -0700248 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700249 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 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700282 * 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.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700284 * @throws Throwable
285 */
286 @Test
287 public void testGetControllerForSwitch() throws Throwable {
288 long dpidRegistered = 1000L;
289 long dpidNotRegistered = 2000L;
290
291 setPathChildrenCache();
292
293 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
294 assertEquals("controller1",controllerForSw);
295
296 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
297 assertEquals(null, controllerForSw);
298 }
299
300 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700301 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
302 * switches controlled by a controller.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700303 * @throws Exception
304 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700305 // TODO: Test after getSwitchesControlledByController() is implemented.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700306 @Ignore @Test
307 public void testGetSwitchesControlledByController() throws Exception {
308 String controllerIdRegistered = "controller1";
309 String dpidRegistered = HexString.toHexString(1000L);
310 String controllerIdNotRegistered = CONTROLLER_ID;
311
312 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
313 assertNotNull(switches);
314 assertTrue(switches.contains(dpidRegistered));
315
316 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
317 assertNotNull(switches);
318 assertEquals(0, switches.size());
319 }
320
321 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700322 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
323 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700324 * @throws Exception
325 */
326 @Test
327 public void testGetAllSwitches() throws Exception {
328 String [] dpids = {
329 HexString.toHexString(1000L),
330 HexString.toHexString(1001L),
331 HexString.toHexString(1002L),
332 };
333
334 setPathChildrenCache();
335
336 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
337 assertNotNull(switches);
338 assertEquals(dpids.length, switches.size());
339 for(String dpid : dpids) {
340 assertTrue(switches.keySet().contains(dpid));
341 }
342 }
343
344 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700345 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700346 */
347 @Test
348 public void testAllocateUniqueIdBlock() {
349 // Number of blocks to be verified that any of them has unique block
350 final int NUM_BLOCKS = 100;
351 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
352
353 for(int i = 0; i < NUM_BLOCKS; ++i) {
354 IdBlock block = registry.allocateUniqueIdBlock();
355 assertNotNull(block);
356 blocks.add(block);
357 }
358
359 for(int i = 0; i < NUM_BLOCKS; ++i) {
360 IdBlock block1 = blocks.get(i);
361 for(int j = i + 1; j < NUM_BLOCKS; ++j) {
362 IdBlock block2 = blocks.get(j);
363 IdBlock lower,higher;
364
365 if(block1.getStart() < block2.getStart()) {
366 lower = block1;
367 higher = block2;
368 } else {
369 lower = block2;
370 higher = block1;
371 }
372
373 assertTrue(lower.getSize() > 0L);
374 assertTrue(higher.getSize() > 0L);
375 assertTrue(lower.getEnd() <= higher.getStart());
376 }
377 }
378 }
379
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700380
381 //-------------------------- Creation of mock objects --------------------------
Naoki Shiotad00accf2013-06-25 14:40:37 -0700382 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700383 * Create mock {@link CuratorFramework} object with initial value below.<br>
384 * [Ctrl ID] : [DPID]<br>
385 * controller1 : 1000<br>
386 * controller2 : 1001<br>
387 * controller2 : 1002<br>
Naoki Shiotad00accf2013-06-25 14:40:37 -0700388 * controller2013 : nothing
389 * @return Created mock object
390 * @throws Exception
391 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700392 @SuppressWarnings({ "serial", "unchecked" })
Naoki Shiotad00accf2013-06-25 14:40:37 -0700393 private CuratorFramework createCuratorFrameworkMock() throws Exception {
394 // Mock of AtomicValue
Naoki Shiotad00accf2013-06-25 14:40:37 -0700395 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
396 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
397 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
398 private long value = 0;
399 @Override
400 public Long answer() throws Throwable {
401 value += ID_BLOCK_SIZE;
402 return value;
403 }
404 }).anyTimes();
405 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
406 private long value = ID_BLOCK_SIZE;
407 @Override
408 public Long answer() throws Throwable {
409 value += ID_BLOCK_SIZE;
410 return value;
411 }
412 }).anyTimes();
413 EasyMock.replay(atomicValue);
414
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700415 // Mock DistributedAtomicLong
Naoki Shiotad00accf2013-06-25 14:40:37 -0700416 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
417 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
418 EasyMock.replay(daLong);
419 PowerMock.expectNew(DistributedAtomicLong.class,
420 new Class<?> [] {CuratorFramework.class, String.class, RetryPolicy.class},
421 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
422 andReturn(daLong).anyTimes();
423 PowerMock.replay(DistributedAtomicLong.class);
424
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700425 // Mock ListenerContainer
Naoki Shiotad00accf2013-06-25 14:40:37 -0700426 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
427 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
428 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
429 @Override
430 public Object answer() throws Throwable {
431 pathChildrenCacheListener = (PathChildrenCacheListener)EasyMock.getCurrentArguments()[0];
432 return null;
433 }
434 }).once();
435 EasyMock.replay(listenerContainer);
436
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700437 // Mock PathChildrenCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700438 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
439 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[] {HexString.toHexString(1000L)}, listenerContainer);
440 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[] {
441 HexString.toHexString(1001L), HexString.toHexString(1002L) },listenerContainer);
442
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700443 // Mock PathChildrenCache constructor
Naoki Shiotad00accf2013-06-25 14:40:37 -0700444 PowerMock.expectNew(PathChildrenCache.class,
445 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
446 andReturn(pathChildrenCacheMain).once();
447 PowerMock.expectNew(PathChildrenCache.class,
448 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
449 andReturn(pathChildrenCache1).once();
450 PowerMock.expectNew(PathChildrenCache.class,
451 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
452 andReturn(pathChildrenCache2).anyTimes();
453 PowerMock.replay(PathChildrenCache.class);
454
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700455 // Mock ServiceCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700456 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
457 serviceCache.start();
458 EasyMock.expectLastCall().once();
459 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService> > () {{
460 add(createServiceInstanceMock("controller1"));
461 add(createServiceInstanceMock("controller2"));
462 }}).anyTimes();
463 EasyMock.replay(serviceCache);
464
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700465 // Mock ServiceCacheBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700466 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
467 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
468 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
469 EasyMock.replay(serviceCacheBuilder);
470
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700471 // Mock ServiceDiscovery
Naoki Shiotad00accf2013-06-25 14:40:37 -0700472 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
473 serviceDiscovery.start();
474 EasyMock.expectLastCall().once();
475 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
476 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
477 EasyMock.expectLastCall().once();
478 EasyMock.replay(serviceDiscovery);
479
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700480 // Mock CuratorFramework
Naoki Shiotad00accf2013-06-25 14:40:37 -0700481 CuratorFramework client = EasyMock.createMock(CuratorFramework.class);
482 client.start();
483 EasyMock.expectLastCall().once();
484 EasyMock.expect(client.usingNamespace(EasyMock.anyObject(String.class))).andReturn(client);
485 EasyMock.replay(client);
486
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700487 // Mock ServiceDiscoveryBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700488 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
489 EasyMock.expect(builder.client(client)).andReturn(builder).once();
490 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
491 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
492 EasyMock.replay(builder);
493
494 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
495 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
496 PowerMock.replay(ServiceDiscoveryBuilder.class);
497
498 return client;
499 }
500
501 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700502 * Create mock {@link ServiceInstance} object using given controller ID.
503 * @param controllerId Controller ID to represent instance's payload (ControllerService).
504 * @return Mock ServiceInstance object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700505 */
506 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
507 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
508 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
509 EasyMock.replay(controllerService);
510
511 @SuppressWarnings("unchecked")
512 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
513 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
514 EasyMock.replay(serviceInstance);
515
516 return serviceInstance;
517 }
518
519 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700520 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700521 * @param controllerId Controller ID to represent current data.
522 * @param paths List of HexString indicating switch's DPID.
523 * @param listener Callback object to be set as Listenable.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700524 * @return Mock PathChildrenCache object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700525 * @throws Exception
526 */
527 private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String [] paths,
528 ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
529 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
530
531 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
532
533 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
534 EasyMock.expectLastCall().anyTimes();
535
536 List<ChildData> childs = new ArrayList<ChildData>();
537 for(String path : paths) {
538 childs.add(createChildDataMockForCurrentData(controllerId,path));
539 }
540 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
541
542 pathChildrenCache.rebuild();
543 EasyMock.expectLastCall().anyTimes();
544
545 EasyMock.replay(pathChildrenCache);
546
547 return pathChildrenCache;
548 }
549
550 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700551 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700552 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
553 * @param controllerId Controller ID
554 * @param path HexString indicating switch's DPID
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700555 * @return Mock ChildData object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700556 */
557 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
558 ChildData data = EasyMock.createMock(ChildData.class);
559 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
560 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
561 EasyMock.replay(data);
562
563 return data;
564 }
565
566 /**
567 * Inject relations between controllers and switches using callback object.
568 * @throws Exception
569 */
570 private void setPathChildrenCache() throws Exception {
571 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700572 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700573 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700574 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700575 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700576 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700577 }
578
579 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700580 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700581 * @param controllerId Controller ID.
582 * @param path HexString of DPID.
583 * @param type Event type to be set to mock object.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700584 * @return Mock PathChildrenCacheEvent object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700585 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700586 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
Naoki Shiotad00accf2013-06-25 14:40:37 -0700587 PathChildrenCacheEvent.Type type) {
588 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
589 ChildData data = EasyMock.createMock(ChildData.class);
590
591 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
592 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
593 EasyMock.replay(data);
594
595 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
596 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
597 EasyMock.replay(event);
598
599 return event;
600 }
601}