blob: 3314ad286356c7b9c75986573eda64bebd0fc913 [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
13import org.easymock.EasyMock;
14import org.easymock.IAnswer;
15import org.junit.After;
16import org.junit.Before;
17import org.junit.Ignore;
18import org.junit.Test;
19import org.junit.runner.RunWith;
20import org.openflow.util.HexString;
21import org.powermock.api.easymock.PowerMock;
22import org.powermock.core.classloader.annotations.PrepareForTest;
23import org.powermock.modules.junit4.PowerMockRunner;
24
25import com.netflix.curator.RetryPolicy;
26import com.netflix.curator.framework.CuratorFramework;
27import com.netflix.curator.framework.CuratorFrameworkFactory;
28import com.netflix.curator.framework.listen.ListenerContainer;
29import com.netflix.curator.framework.recipes.atomic.AtomicValue;
30import com.netflix.curator.framework.recipes.atomic.DistributedAtomicLong;
31import com.netflix.curator.framework.recipes.cache.ChildData;
32import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
33import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
34import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
35import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
36import com.netflix.curator.framework.recipes.leader.LeaderLatch;
37import com.netflix.curator.x.discovery.ServiceCache;
38import com.netflix.curator.x.discovery.ServiceCacheBuilder;
39import com.netflix.curator.x.discovery.ServiceDiscovery;
40import com.netflix.curator.x.discovery.ServiceDiscoveryBuilder;
41import com.netflix.curator.x.discovery.ServiceInstance;
42
43/**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070044 * Unit test for {@link ZookeeperRegistry}.
45 * NOTE: {@link FloodlightTestCase} conflicts with PowerMock. If FloodLight-related methods need to be tested,
Naoki Shiotad00accf2013-06-25 14:40:37 -070046 * implement another test class to test them.
47 * @author Naoki Shiota
48 *
49 */
50@RunWith(PowerMockRunner.class)
51@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
52 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
53 ZookeeperRegistry.SwitchPathCacheListener.class})
54public class ZookeeperRegistryTest extends FloodlightTestCase {
55 private final static Long ID_BLOCK_SIZE = 0x100000000L;
56
57 protected ZookeeperRegistry registry;
58 protected CuratorFramework client;
59
60 protected PathChildrenCacheListener pathChildrenCacheListener;
61 protected final String CONTROLLER_ID = "controller2013";
62
63 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070064 * Initialize {@link ZookeeperRegistry} Object and inject initial value with {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
65 * This setup code also tests {@link ZookeeperRegistry#init(FloodlightModuleContext)} method itself.
Naoki Shiotad00accf2013-06-25 14:40:37 -070066 */
67 @Before
68 public void setUp() throws Exception {
69 super.setUp();
70
71 pathChildrenCacheListener = null;
72
73 // Mock of CuratorFramework
74 client = createCuratorFrameworkMock();
75
76 // 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);
81
82 FloodlightModuleContext fmc = new FloodlightModuleContext();
83 registry = new ZookeeperRegistry();
84 fmc.addService(ZookeeperRegistry.class, registry);
85
86 registry.init(fmc);
87
88 PowerMock.verify(client, CuratorFrameworkFactory.class);
89 }
90
91 /**
92 * Clean up member variables (empty for now).
93 */
94 @After
95 public void tearDown() throws Exception {
96 super.tearDown();
97 }
98
99 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700100 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
101 * (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 -0700102 */
103 @Test
104 public void testRegisterController() {
105 String controllerIdToRegister = "controller2013";
106
107 try {
108 registry.registerController(controllerIdToRegister);
109 } catch (RegistryException e) {
110 e.printStackTrace();
111 fail(e.getMessage());
112 }
113 }
114
115 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700116 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700117 * @throws Exception
118 */
119 @Test
120 public void testGetControllerId() throws Exception {
121 String controllerIdToRegister = "controller1";
122
123 // try before controller is registered
124 String controllerId = registry.getControllerId();
125 assertNull(controllerId);
126
127 // register
128 registry.registerController(controllerIdToRegister);
129
130 // call getControllerId and verify
131 controllerId = registry.getControllerId();
132 assertNotNull(controllerId);
133 assertEquals(controllerIdToRegister, controllerId);
134 }
135
136 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700137 * 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}.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700140 * @throws Exception
141 */
142 @Test
143 public void testGetAllControllers() throws Exception {
144 String controllerIdRegistered = "controller1";
145 String controllerIdNotRegistered = "controller2013";
146
Naoki Shiotad00accf2013-06-25 14:40:37 -0700147 try {
148 Collection<String> ctrls = registry.getAllControllers();
149 assertTrue(ctrls.contains(controllerIdRegistered));
150 assertFalse(ctrls.contains(controllerIdNotRegistered));
151 } catch (RegistryException e) {
152 e.printStackTrace();
153 fail(e.getMessage());
154 }
155 }
156
157 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700158 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
159 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
160 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700161 * @throws Exception
162 */
163 @Test
164 public void testRequestControl() throws Exception {
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700165 // Mock LeaderLatch
Naoki Shiotad00accf2013-06-25 14:40:37 -0700166 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
167 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
168 EasyMock.expectLastCall().once();
169 latch.start();
170 EasyMock.expectLastCall().once();
171 EasyMock.replay(latch);
172
173 PowerMock.expectNew(LeaderLatch.class,
174 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700175 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700176 PowerMock.replay(LeaderLatch.class);
177
178 String controllerId = "controller2013";
179 registry.registerController(controllerId);
180
181 LoggingCallback callback = new LoggingCallback(1);
182 long dpidToRequest = 2000L;
183
184 try {
185 registry.requestControl(dpidToRequest, callback);
186 } catch (RegistryException e) {
187 e.printStackTrace();
188 fail(e.getMessage());
189 }
190
191 EasyMock.verify(latch);
192 }
193
194 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700195 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
196 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
197 * {@link LeaderLatch} object and verify latch is correctly set up.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700198 * @throws Exception
199 */
200 @Test
201 public void testReleaseControl() throws Exception {
202 // Mock of LeaderLatch
203 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
204 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
205 EasyMock.expectLastCall().once();
206 latch.start();
207 EasyMock.expectLastCall().once();
208 latch.removeAllListeners();
209 EasyMock.expectLastCall().once();
210 latch.close();
211 EasyMock.expectLastCall().once();
212 EasyMock.replay(latch);
213
214 PowerMock.expectNew(LeaderLatch.class,
215 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700216 .andReturn(latch).once();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700217 PowerMock.replay(LeaderLatch.class);
218
219 String controllerId = "controller2013";
220 registry.registerController(controllerId);
221
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700222 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700223 LoggingCallback callback = new LoggingCallback(1);
224
Naoki Shiotad00accf2013-06-25 14:40:37 -0700225 registry.requestControl(dpidToRequest, callback);
226 registry.releaseControl(dpidToRequest);
227
Naoki Shiotad00accf2013-06-25 14:40:37 -0700228 EasyMock.verify(latch);
229 }
230
231 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700232 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700233 * @throws Exception
234 */
235 @Test
236 public void testHasControl() throws Exception {
237 // Mock of LeaderLatch
238 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
239 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
240 EasyMock.expectLastCall().once();
241 latch.start();
242 EasyMock.expectLastCall().once();
243 EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
244 latch.removeAllListeners();
245 EasyMock.expectLastCall().once();
246 latch.close();
247 EasyMock.expectLastCall().once();
248 EasyMock.replay(latch);
249
250 PowerMock.expectNew(LeaderLatch.class,
251 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
252 .andReturn(latch);
253 PowerMock.replay(LeaderLatch.class);
254
255 String controllerId = "controller2013";
256 registry.registerController(controllerId);
257
258 long dpidToRequest = 2000L;
259 LoggingCallback callback = new LoggingCallback(2);
260
261 // Test before request control
262 assertFalse(registry.hasControl(dpidToRequest));
263
264 registry.requestControl(dpidToRequest, callback);
265
266 // Test after request control
267 assertTrue(registry.hasControl(dpidToRequest));
268
269 registry.releaseControl(dpidToRequest);
270
271 // Test after release control
272 assertFalse(registry.hasControl(dpidToRequest));
273
274 EasyMock.verify(latch);
275 }
276
277 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700278 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)} correctly returns controller ID of specific switch.
279 * Relation between controllers and switches are defined by {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700280 * @throws Throwable
281 */
282 @Test
283 public void testGetControllerForSwitch() throws Throwable {
284 long dpidRegistered = 1000L;
285 long dpidNotRegistered = 2000L;
286
287 setPathChildrenCache();
288
289 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
290 assertEquals("controller1",controllerForSw);
291
292 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
293 assertEquals(null, controllerForSw);
294 }
295
296 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700297 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
298 * switches controlled by a controller.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700299 * @throws Exception
300 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700301 // TODO: Test after getSwitchesControlledByController() is implemented.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700302 @Ignore @Test
303 public void testGetSwitchesControlledByController() throws Exception {
304 String controllerIdRegistered = "controller1";
305 String dpidRegistered = HexString.toHexString(1000L);
306 String controllerIdNotRegistered = CONTROLLER_ID;
307
308 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
309 assertNotNull(switches);
310 assertTrue(switches.contains(dpidRegistered));
311
312 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
313 assertNotNull(switches);
314 assertEquals(0, switches.size());
315 }
316
317 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700318 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
319 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700320 * @throws Exception
321 */
322 @Test
323 public void testGetAllSwitches() throws Exception {
324 String [] dpids = {
325 HexString.toHexString(1000L),
326 HexString.toHexString(1001L),
327 HexString.toHexString(1002L),
328 };
329
330 setPathChildrenCache();
331
332 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
333 assertNotNull(switches);
334 assertEquals(dpids.length, switches.size());
335 for(String dpid : dpids) {
336 assertTrue(switches.keySet().contains(dpid));
337 }
338 }
339
340 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700341 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700342 */
343 @Test
344 public void testAllocateUniqueIdBlock() {
345 // Number of blocks to be verified that any of them has unique block
346 final int NUM_BLOCKS = 100;
347 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
348
349 for(int i = 0; i < NUM_BLOCKS; ++i) {
350 IdBlock block = registry.allocateUniqueIdBlock();
351 assertNotNull(block);
352 blocks.add(block);
353 }
354
355 for(int i = 0; i < NUM_BLOCKS; ++i) {
356 IdBlock block1 = blocks.get(i);
357 for(int j = i + 1; j < NUM_BLOCKS; ++j) {
358 IdBlock block2 = blocks.get(j);
359 IdBlock lower,higher;
360
361 if(block1.getStart() < block2.getStart()) {
362 lower = block1;
363 higher = block2;
364 } else {
365 lower = block2;
366 higher = block1;
367 }
368
369 assertTrue(lower.getSize() > 0L);
370 assertTrue(higher.getSize() > 0L);
371 assertTrue(lower.getEnd() <= higher.getStart());
372 }
373 }
374 }
375
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700376
377 //-------------------------- Creation of mock objects --------------------------
Naoki Shiotad00accf2013-06-25 14:40:37 -0700378 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700379 * Create mock {@link CuratorFramework} object with initial value below.<br>
380 * [Ctrl ID] : [DPID]<br>
381 * controller1 : 1000<br>
382 * controller2 : 1001<br>
383 * controller2 : 1002<br>
Naoki Shiotad00accf2013-06-25 14:40:37 -0700384 * controller2013 : nothing
385 * @return Created mock object
386 * @throws Exception
387 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700388 @SuppressWarnings({ "serial", "unchecked" })
Naoki Shiotad00accf2013-06-25 14:40:37 -0700389 private CuratorFramework createCuratorFrameworkMock() throws Exception {
390 // Mock of AtomicValue
Naoki Shiotad00accf2013-06-25 14:40:37 -0700391 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
392 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
393 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
394 private long value = 0;
395 @Override
396 public Long answer() throws Throwable {
397 value += ID_BLOCK_SIZE;
398 return value;
399 }
400 }).anyTimes();
401 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
402 private long value = ID_BLOCK_SIZE;
403 @Override
404 public Long answer() throws Throwable {
405 value += ID_BLOCK_SIZE;
406 return value;
407 }
408 }).anyTimes();
409 EasyMock.replay(atomicValue);
410
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700411 // Mock DistributedAtomicLong
Naoki Shiotad00accf2013-06-25 14:40:37 -0700412 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
413 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
414 EasyMock.replay(daLong);
415 PowerMock.expectNew(DistributedAtomicLong.class,
416 new Class<?> [] {CuratorFramework.class, String.class, RetryPolicy.class},
417 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
418 andReturn(daLong).anyTimes();
419 PowerMock.replay(DistributedAtomicLong.class);
420
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700421 // Mock ListenerContainer
Naoki Shiotad00accf2013-06-25 14:40:37 -0700422 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
423 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
424 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
425 @Override
426 public Object answer() throws Throwable {
427 pathChildrenCacheListener = (PathChildrenCacheListener)EasyMock.getCurrentArguments()[0];
428 return null;
429 }
430 }).once();
431 EasyMock.replay(listenerContainer);
432
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700433 // Mock PathChildrenCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700434 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
435 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[] {HexString.toHexString(1000L)}, listenerContainer);
436 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[] {
437 HexString.toHexString(1001L), HexString.toHexString(1002L) },listenerContainer);
438
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700439 // Mock PathChildrenCache constructor
Naoki Shiotad00accf2013-06-25 14:40:37 -0700440 PowerMock.expectNew(PathChildrenCache.class,
441 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
442 andReturn(pathChildrenCacheMain).once();
443 PowerMock.expectNew(PathChildrenCache.class,
444 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
445 andReturn(pathChildrenCache1).once();
446 PowerMock.expectNew(PathChildrenCache.class,
447 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
448 andReturn(pathChildrenCache2).anyTimes();
449 PowerMock.replay(PathChildrenCache.class);
450
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700451 // Mock ServiceCache
Naoki Shiotad00accf2013-06-25 14:40:37 -0700452 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
453 serviceCache.start();
454 EasyMock.expectLastCall().once();
455 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService> > () {{
456 add(createServiceInstanceMock("controller1"));
457 add(createServiceInstanceMock("controller2"));
458 }}).anyTimes();
459 EasyMock.replay(serviceCache);
460
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700461 // Mock ServiceCacheBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700462 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
463 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
464 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
465 EasyMock.replay(serviceCacheBuilder);
466
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700467 // Mock ServiceDiscovery
Naoki Shiotad00accf2013-06-25 14:40:37 -0700468 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
469 serviceDiscovery.start();
470 EasyMock.expectLastCall().once();
471 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
472 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
473 EasyMock.expectLastCall().once();
474 EasyMock.replay(serviceDiscovery);
475
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700476 // Mock CuratorFramework
Naoki Shiotad00accf2013-06-25 14:40:37 -0700477 CuratorFramework client = EasyMock.createMock(CuratorFramework.class);
478 client.start();
479 EasyMock.expectLastCall().once();
480 EasyMock.expect(client.usingNamespace(EasyMock.anyObject(String.class))).andReturn(client);
481 EasyMock.replay(client);
482
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700483 // Mock ServiceDiscoveryBuilder
Naoki Shiotad00accf2013-06-25 14:40:37 -0700484 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
485 EasyMock.expect(builder.client(client)).andReturn(builder).once();
486 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
487 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
488 EasyMock.replay(builder);
489
490 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
491 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
492 PowerMock.replay(ServiceDiscoveryBuilder.class);
493
494 return client;
495 }
496
497 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700498 * Create mock {@link ServiceInstance} object using given controller ID.
499 * @param controllerId Controller ID to represent instance's payload (ControllerService).
500 * @return Mock ServiceInstance object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700501 */
502 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
503 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
504 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
505 EasyMock.replay(controllerService);
506
507 @SuppressWarnings("unchecked")
508 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
509 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
510 EasyMock.replay(serviceInstance);
511
512 return serviceInstance;
513 }
514
515 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700516 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700517 * @param controllerId Controller ID to represent current data.
518 * @param paths List of HexString indicating switch's DPID.
519 * @param listener Callback object to be set as Listenable.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700520 * @return Mock PathChildrenCache object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700521 * @throws Exception
522 */
523 private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String [] paths,
524 ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
525 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
526
527 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
528
529 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
530 EasyMock.expectLastCall().anyTimes();
531
532 List<ChildData> childs = new ArrayList<ChildData>();
533 for(String path : paths) {
534 childs.add(createChildDataMockForCurrentData(controllerId,path));
535 }
536 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
537
538 pathChildrenCache.rebuild();
539 EasyMock.expectLastCall().anyTimes();
540
541 EasyMock.replay(pathChildrenCache);
542
543 return pathChildrenCache;
544 }
545
546 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700547 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700548 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
549 * @param controllerId Controller ID
550 * @param path HexString indicating switch's DPID
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700551 * @return Mock ChildData object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700552 */
553 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
554 ChildData data = EasyMock.createMock(ChildData.class);
555 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
556 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
557 EasyMock.replay(data);
558
559 return data;
560 }
561
562 /**
563 * Inject relations between controllers and switches using callback object.
564 * @throws Exception
565 */
566 private void setPathChildrenCache() throws Exception {
567 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700568 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700569 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700570 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700571 pathChildrenCacheListener.childEvent(client,
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700572 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700573 }
574
575 /**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700576 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
Naoki Shiotad00accf2013-06-25 14:40:37 -0700577 * @param controllerId Controller ID.
578 * @param path HexString of DPID.
579 * @param type Event type to be set to mock object.
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700580 * @return Mock PathChildrenCacheEvent object
Naoki Shiotad00accf2013-06-25 14:40:37 -0700581 */
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -0700582 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
Naoki Shiotad00accf2013-06-25 14:40:37 -0700583 PathChildrenCacheEvent.Type type) {
584 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
585 ChildData data = EasyMock.createMock(ChildData.class);
586
587 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
588 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
589 EasyMock.replay(data);
590
591 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
592 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
593 EasyMock.replay(event);
594
595 return event;
596 }
597}