blob: 774a9d47096c7af8ea6f440a947a52bf1f72e671 [file] [log] [blame]
Naoki Shiotad00accf2013-06-25 14:40:37 -07001package net.onrc.onos.registry.controller;
2
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;
10import net.onrc.onos.registry.controller.StandaloneRegistryTest.LoggingCallback;
11import net.onrc.onos.registry.controller.ZookeeperRegistry.SwitchLeaderListener;
12
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,
Naoki Shiotad00accf2013-06-25 14:40:37 -070045 * implement another test class to test them.
46 * @author Naoki Shiota
47 *
48 */
49@RunWith(PowerMockRunner.class)
50@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
51 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
52 ZookeeperRegistry.SwitchPathCacheListener.class})
53public class ZookeeperRegistryTest extends FloodlightTestCase {
54 private final static Long ID_BLOCK_SIZE = 0x100000000L;
55
56 protected ZookeeperRegistry registry;
57 protected CuratorFramework client;
58
59 protected PathChildrenCacheListener pathChildrenCacheListener;
60 protected final String CONTROLLER_ID = "controller2013";
61
62 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070063 * 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.
Naoki Shiotad00accf2013-06-25 14:40:37 -070065 */
66 @Before
67 public void setUp() throws Exception {
68 super.setUp();
69
70 pathChildrenCacheListener = null;
71
72 // Mock of CuratorFramework
73 client = createCuratorFrameworkMock();
74
75 // 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);
80
81 FloodlightModuleContext fmc = new FloodlightModuleContext();
82 registry = new ZookeeperRegistry();
83 fmc.addService(ZookeeperRegistry.class, registry);
84
85 registry.init(fmc);
86
87 PowerMock.verify(client, CuratorFrameworkFactory.class);
88 }
89
90 /**
91 * Clean up member variables (empty for now).
92 */
93 @After
94 public void tearDown() throws Exception {
95 super.tearDown();
96 }
97
98 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070099 * 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.)
Naoki Shiotad00accf2013-06-25 14:40:37 -0700101 */
102 @Test
103 public void testRegisterController() {
104 String controllerIdToRegister = "controller2013";
105
106 try {
107 registry.registerController(controllerIdToRegister);
108 } catch (RegistryException e) {
109 e.printStackTrace();
110 fail(e.getMessage());
111 }
112 }
113
114 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700115 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700116 * @throws Exception
117 */
118 @Test
119 public void testGetControllerId() throws Exception {
120 String controllerIdToRegister = "controller1";
121
122 // try before controller is registered
123 String controllerId = registry.getControllerId();
124 assertNull(controllerId);
125
126 // register
127 registry.registerController(controllerIdToRegister);
128
129 // call getControllerId and verify
130 controllerId = registry.getControllerId();
131 assertNotNull(controllerId);
132 assertEquals(controllerIdToRegister, controllerId);
133 }
134
135 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700136 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
137 * Controllers to be returned are injected while setup. See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
138 * to what controllers are injected using mock {@link ServiceCache}.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700139 * @throws Exception
140 */
141 @Test
142 public void testGetAllControllers() throws Exception {
143 String controllerIdRegistered = "controller1";
144 String controllerIdNotRegistered = "controller2013";
145
Naoki Shiotad00accf2013-06-25 14:40:37 -0700146 try {
147 Collection<String> ctrls = registry.getAllControllers();
148 assertTrue(ctrls.contains(controllerIdRegistered));
149 assertFalse(ctrls.contains(controllerIdNotRegistered));
150 } catch (RegistryException e) {
151 e.printStackTrace();
152 fail(e.getMessage());
153 }
154 }
155
156 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700157 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
158 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
159 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700160 * @throws Exception
161 */
162 @Test
163 public void testRequestControl() throws Exception {
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700164 // Mock LeaderLatch
Naoki Shiotad00accf2013-06-25 14:40:37 -0700165 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
166 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
167 EasyMock.expectLastCall().once();
168 latch.start();
169 EasyMock.expectLastCall().once();
170 EasyMock.replay(latch);
171
172 PowerMock.expectNew(LeaderLatch.class,
173 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700174 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700175 PowerMock.replay(LeaderLatch.class);
176
177 String controllerId = "controller2013";
178 registry.registerController(controllerId);
179
180 LoggingCallback callback = new LoggingCallback(1);
181 long dpidToRequest = 2000L;
182
183 try {
184 registry.requestControl(dpidToRequest, callback);
185 } catch (RegistryException e) {
186 e.printStackTrace();
187 fail(e.getMessage());
188 }
189
190 EasyMock.verify(latch);
191 }
192
193 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700194 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
195 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
196 * {@link LeaderLatch} object and verify latch is correctly set up.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700197 * @throws Exception
198 */
199 @Test
200 public void testReleaseControl() throws Exception {
201 // Mock of LeaderLatch
202 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
203 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
204 EasyMock.expectLastCall().once();
205 latch.start();
206 EasyMock.expectLastCall().once();
Jonathan Hart116b1fe2014-03-14 18:53:47 -0700207 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700208 EasyMock.expectLastCall().once();
209 latch.close();
210 EasyMock.expectLastCall().once();
211 EasyMock.replay(latch);
212
213 PowerMock.expectNew(LeaderLatch.class,
214 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700215 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700216 PowerMock.replay(LeaderLatch.class);
217
218 String controllerId = "controller2013";
219 registry.registerController(controllerId);
220
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700221 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700222 LoggingCallback callback = new LoggingCallback(1);
223
Naoki Shiotad00accf2013-06-25 14:40:37 -0700224 registry.requestControl(dpidToRequest, callback);
225 registry.releaseControl(dpidToRequest);
226
Naoki Shiotad00accf2013-06-25 14:40:37 -0700227 EasyMock.verify(latch);
228 }
229
230 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700231 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700232 * @throws Exception
233 */
234 @Test
235 public void testHasControl() throws Exception {
236 // Mock of LeaderLatch
237 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
238 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
239 EasyMock.expectLastCall().once();
240 latch.start();
241 EasyMock.expectLastCall().once();
242 EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
Jonathan Hart116b1fe2014-03-14 18:53:47 -0700243 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700244 EasyMock.expectLastCall().once();
245 latch.close();
246 EasyMock.expectLastCall().once();
247 EasyMock.replay(latch);
248
249 PowerMock.expectNew(LeaderLatch.class,
250 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
251 .andReturn(latch);
252 PowerMock.replay(LeaderLatch.class);
253
254 String controllerId = "controller2013";
255 registry.registerController(controllerId);
256
257 long dpidToRequest = 2000L;
258 LoggingCallback callback = new LoggingCallback(2);
259
260 // Test before request control
261 assertFalse(registry.hasControl(dpidToRequest));
262
263 registry.requestControl(dpidToRequest, callback);
264
265 // Test after request control
266 assertTrue(registry.hasControl(dpidToRequest));
267
268 registry.releaseControl(dpidToRequest);
269
270 // Test after release control
271 assertFalse(registry.hasControl(dpidToRequest));
272
273 EasyMock.verify(latch);
274 }
275
276 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700277 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)} correctly returns controller ID of specific switch.
278 * Relation between controllers and switches are defined by {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700279 * @throws Throwable
280 */
281 @Test
282 public void testGetControllerForSwitch() throws Throwable {
283 long dpidRegistered = 1000L;
284 long dpidNotRegistered = 2000L;
285
286 setPathChildrenCache();
287
288 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
289 assertEquals("controller1",controllerForSw);
290
291 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
292 assertEquals(null, controllerForSw);
293 }
294
295 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700296 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
297 * switches controlled by a controller.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700298 * @throws Exception
299 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700300 // TODO: Test after getSwitchesControlledByController() is implemented.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700301 @Ignore @Test
302 public void testGetSwitchesControlledByController() throws Exception {
303 String controllerIdRegistered = "controller1";
304 String dpidRegistered = HexString.toHexString(1000L);
305 String controllerIdNotRegistered = CONTROLLER_ID;
306
307 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
308 assertNotNull(switches);
309 assertTrue(switches.contains(dpidRegistered));
310
311 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
312 assertNotNull(switches);
313 assertEquals(0, switches.size());
314 }
315
316 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700317 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
318 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700319 * @throws Exception
320 */
321 @Test
322 public void testGetAllSwitches() throws Exception {
323 String [] dpids = {
324 HexString.toHexString(1000L),
325 HexString.toHexString(1001L),
326 HexString.toHexString(1002L),
327 };
328
329 setPathChildrenCache();
330
331 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
332 assertNotNull(switches);
333 assertEquals(dpids.length, switches.size());
334 for(String dpid : dpids) {
335 assertTrue(switches.keySet().contains(dpid));
336 }
337 }
338
339 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700340 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700341 */
342 @Test
343 public void testAllocateUniqueIdBlock() {
344 // Number of blocks to be verified that any of them has unique block
345 final int NUM_BLOCKS = 100;
346 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
347
348 for(int i = 0; i < NUM_BLOCKS; ++i) {
349 IdBlock block = registry.allocateUniqueIdBlock();
350 assertNotNull(block);
351 blocks.add(block);
352 }
353
354 for(int i = 0; i < NUM_BLOCKS; ++i) {
355 IdBlock block1 = blocks.get(i);
356 for(int j = i + 1; j < NUM_BLOCKS; ++j) {
357 IdBlock block2 = blocks.get(j);
358 IdBlock lower,higher;
359
360 if(block1.getStart() < block2.getStart()) {
361 lower = block1;
362 higher = block2;
363 } else {
364 lower = block2;
365 higher = block1;
366 }
367
368 assertTrue(lower.getSize() > 0L);
369 assertTrue(higher.getSize() > 0L);
370 assertTrue(lower.getEnd() <= higher.getStart());
371 }
372 }
373 }
374
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700375
376 //-------------------------- Creation of mock objects --------------------------
Naoki Shiotad00accf2013-06-25 14:40:37 -0700377 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700378 * Create mock {@link CuratorFramework} object with initial value below.<br>
379 * [Ctrl ID] : [DPID]<br>
380 * controller1 : 1000<br>
381 * controller2 : 1001<br>
382 * controller2 : 1002<br>
Naoki Shiotad00accf2013-06-25 14:40:37 -0700383 * controller2013 : nothing
384 * @return Created mock object
385 * @throws Exception
386 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700387 @SuppressWarnings({ "serial", "unchecked" })
Naoki Shiotad00accf2013-06-25 14:40:37 -0700388 private CuratorFramework createCuratorFrameworkMock() throws Exception {
389 // Mock of AtomicValue
Naoki Shiotad00accf2013-06-25 14:40:37 -0700390 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
391 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
392 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
393 private long value = 0;
394 @Override
395 public Long answer() throws Throwable {
396 value += ID_BLOCK_SIZE;
397 return value;
398 }
399 }).anyTimes();
400 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
401 private long value = ID_BLOCK_SIZE;
402 @Override
403 public Long answer() throws Throwable {
404 value += ID_BLOCK_SIZE;
405 return value;
406 }
407 }).anyTimes();
408 EasyMock.replay(atomicValue);
409
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700410 // Mock DistributedAtomicLong
Naoki Shiotad00accf2013-06-25 14:40:37 -0700411 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
412 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
413 EasyMock.replay(daLong);
414 PowerMock.expectNew(DistributedAtomicLong.class,
415 new Class<?> [] {CuratorFramework.class, String.class, RetryPolicy.class},
416 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
417 andReturn(daLong).anyTimes();
418 PowerMock.replay(DistributedAtomicLong.class);
419
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700420 // Mock ListenerContainer
Naoki Shiotad00accf2013-06-25 14:40:37 -0700421 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
422 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
423 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
424 @Override
425 public Object answer() throws Throwable {
426 pathChildrenCacheListener = (PathChildrenCacheListener)EasyMock.getCurrentArguments()[0];
427 return null;
428 }
429 }).once();
430 EasyMock.replay(listenerContainer);
431
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700432 // Mock PathChildrenCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700433 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
434 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[] {HexString.toHexString(1000L)}, listenerContainer);
435 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[] {
436 HexString.toHexString(1001L), HexString.toHexString(1002L) },listenerContainer);
437
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700438 // Mock PathChildrenCache constructor
Naoki Shiotad00accf2013-06-25 14:40:37 -0700439 PowerMock.expectNew(PathChildrenCache.class,
440 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
441 andReturn(pathChildrenCacheMain).once();
442 PowerMock.expectNew(PathChildrenCache.class,
443 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
444 andReturn(pathChildrenCache1).once();
445 PowerMock.expectNew(PathChildrenCache.class,
446 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
447 andReturn(pathChildrenCache2).anyTimes();
448 PowerMock.replay(PathChildrenCache.class);
449
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700450 // Mock ServiceCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700451 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
452 serviceCache.start();
453 EasyMock.expectLastCall().once();
454 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService> > () {{
455 add(createServiceInstanceMock("controller1"));
456 add(createServiceInstanceMock("controller2"));
457 }}).anyTimes();
458 EasyMock.replay(serviceCache);
459
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700460 // Mock ServiceCacheBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700461 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
462 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
463 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
464 EasyMock.replay(serviceCacheBuilder);
465
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700466 // Mock ServiceDiscovery
Naoki Shiotad00accf2013-06-25 14:40:37 -0700467 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
468 serviceDiscovery.start();
469 EasyMock.expectLastCall().once();
470 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
471 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
472 EasyMock.expectLastCall().once();
473 EasyMock.replay(serviceDiscovery);
474
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700475 // Mock CuratorFramework
Naoki Shiotad00accf2013-06-25 14:40:37 -0700476 CuratorFramework client = EasyMock.createMock(CuratorFramework.class);
477 client.start();
478 EasyMock.expectLastCall().once();
479 EasyMock.expect(client.usingNamespace(EasyMock.anyObject(String.class))).andReturn(client);
480 EasyMock.replay(client);
481
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700482 // Mock ServiceDiscoveryBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700483 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
484 EasyMock.expect(builder.client(client)).andReturn(builder).once();
485 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
486 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
487 EasyMock.replay(builder);
488
489 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
490 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
491 PowerMock.replay(ServiceDiscoveryBuilder.class);
492
493 return client;
494 }
495
496 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700497 * Create mock {@link ServiceInstance} object using given controller ID.
498 * @param controllerId Controller ID to represent instance's payload (ControllerService).
499 * @return Mock ServiceInstance object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700500 */
501 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
502 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
503 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
504 EasyMock.replay(controllerService);
505
506 @SuppressWarnings("unchecked")
507 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
508 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
509 EasyMock.replay(serviceInstance);
510
511 return serviceInstance;
512 }
513
514 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700515 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700516 * @param controllerId Controller ID to represent current data.
517 * @param paths List of HexString indicating switch's DPID.
518 * @param listener Callback object to be set as Listenable.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700519 * @return Mock PathChildrenCache object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700520 * @throws Exception
521 */
522 private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String [] paths,
523 ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
524 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
525
526 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
527
528 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
529 EasyMock.expectLastCall().anyTimes();
530
531 List<ChildData> childs = new ArrayList<ChildData>();
532 for(String path : paths) {
533 childs.add(createChildDataMockForCurrentData(controllerId,path));
534 }
535 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
536
537 pathChildrenCache.rebuild();
538 EasyMock.expectLastCall().anyTimes();
539
540 EasyMock.replay(pathChildrenCache);
541
542 return pathChildrenCache;
543 }
544
545 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700546 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700547 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
548 * @param controllerId Controller ID
549 * @param path HexString indicating switch's DPID
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700550 * @return Mock ChildData object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700551 */
552 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
553 ChildData data = EasyMock.createMock(ChildData.class);
554 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
555 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
556 EasyMock.replay(data);
557
558 return data;
559 }
560
561 /**
562 * Inject relations between controllers and switches using callback object.
563 * @throws Exception
564 */
565 private void setPathChildrenCache() throws Exception {
566 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700567 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700568 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700569 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700570 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700571 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700572 }
573
574 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700575 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700576 * @param controllerId Controller ID.
577 * @param path HexString of DPID.
578 * @param type Event type to be set to mock object.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700579 * @return Mock PathChildrenCacheEvent object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700580 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700581 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
Naoki Shiotad00accf2013-06-25 14:40:37 -0700582 PathChildrenCacheEvent.Type type) {
583 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
584 ChildData data = EasyMock.createMock(ChildData.class);
585
586 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
587 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
588 EasyMock.replay(data);
589
590 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
591 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
592 EasyMock.replay(event);
593
594 return event;
595 }
596}