blob: 3ac2c96f80d851b5e5b3b87dc480bbde6f130977 [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;
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -070012import net.onrc.onos.core.util.OnosInstanceId;
Naoki Shiotad00accf2013-06-25 14:40:37 -070013
Jonathan Hart116b1fe2014-03-14 18:53:47 -070014import org.apache.curator.RetryPolicy;
15import org.apache.curator.framework.CuratorFramework;
16import org.apache.curator.framework.CuratorFrameworkFactory;
17import org.apache.curator.framework.listen.ListenerContainer;
18import org.apache.curator.framework.recipes.atomic.AtomicValue;
19import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
20import org.apache.curator.framework.recipes.cache.ChildData;
21import org.apache.curator.framework.recipes.cache.PathChildrenCache;
22import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
23import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
24import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
25import org.apache.curator.framework.recipes.leader.LeaderLatch;
26import org.apache.curator.x.discovery.ServiceCache;
27import org.apache.curator.x.discovery.ServiceCacheBuilder;
28import org.apache.curator.x.discovery.ServiceDiscovery;
29import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
30import org.apache.curator.x.discovery.ServiceInstance;
Naoki Shiotad00accf2013-06-25 14:40:37 -070031import org.easymock.EasyMock;
32import org.easymock.IAnswer;
33import org.junit.After;
34import org.junit.Before;
35import org.junit.Ignore;
36import org.junit.Test;
37import org.junit.runner.RunWith;
Naoki Shiotad00accf2013-06-25 14:40:37 -070038import org.powermock.api.easymock.PowerMock;
39import org.powermock.core.classloader.annotations.PrepareForTest;
40import org.powermock.modules.junit4.PowerMockRunner;
Jonathan Hartc78b8f62014-08-07 22:31:09 -070041import org.projectfloodlight.openflow.util.HexString;
Naoki Shiotad00accf2013-06-25 14:40:37 -070042
Naoki Shiotad00accf2013-06-25 14:40:37 -070043/**
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,
Ray Milkey269ffb92014-04-03 14:43:30 -070046 * implement another test class to test them.
Naoki Shiotad00accf2013-06-25 14:40:37 -070047 */
48@RunWith(PowerMockRunner.class)
49@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
Ray Milkey269ffb92014-04-03 14:43:30 -070050 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070051 ZookeeperRegistry.SwitchPathCacheListener.class })
Naoki Shiotad00accf2013-06-25 14:40:37 -070052public class ZookeeperRegistryTest extends FloodlightTestCase {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070053 private static final Long ID_BLOCK_SIZE = 0x100000000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -070054
Ray Milkey269ffb92014-04-03 14:43:30 -070055 protected ZookeeperRegistry registry;
56 protected CuratorFramework client;
Naoki Shiotad00accf2013-06-25 14:40:37 -070057
Ray Milkey269ffb92014-04-03 14:43:30 -070058 protected PathChildrenCacheListener pathChildrenCacheListener;
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070059 protected static final String CONTROLLER_ID = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -070060
Ray Milkey269ffb92014-04-03 14:43:30 -070061 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -070062 * Initialize {@link ZookeeperRegistry} Object and inject initial value with
63 * {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
Ray Milkey269ffb92014-04-03 14:43:30 -070064 * 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.
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700102 * (Exceptions are usually out of test target,
103 * but {@link ZookeeperRegistry#registerController(String)}
104 * throws an exception in case of invalid registration.)
Ray Milkey269ffb92014-04-03 14:43:30 -0700105 */
106 @Test
107 public void testRegisterController() {
108 String controllerIdToRegister = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700109
Ray Milkey269ffb92014-04-03 14:43:30 -0700110 try {
111 registry.registerController(controllerIdToRegister);
112 } catch (RegistryException e) {
113 e.printStackTrace();
114 fail(e.getMessage());
115 }
116 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700117
Ray Milkey269ffb92014-04-03 14:43:30 -0700118 /**
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700119 * Test if {@link ZookeeperRegistry#getOnosInstanceId()} correctly returns
120 * registered ID.
Ray Milkey269ffb92014-04-03 14:43:30 -0700121 *
122 * @throws Exception
123 */
124 @Test
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700125 public void testGetOnosInstanceId() throws Exception {
Ray Milkey269ffb92014-04-03 14:43:30 -0700126 String controllerIdToRegister = "controller1";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700127
Ray Milkey269ffb92014-04-03 14:43:30 -0700128 // try before controller is registered
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700129 OnosInstanceId onosInstanceId = registry.getOnosInstanceId();
130 assertNull(onosInstanceId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700131
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 // register
133 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700134
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700135 // call getOnosInstanceId and verify
136 onosInstanceId = registry.getOnosInstanceId();
137 assertNotNull(onosInstanceId);
138 assertEquals(controllerIdToRegister, onosInstanceId.toString());
Ray Milkey269ffb92014-04-03 14:43:30 -0700139 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700140
Ray Milkey269ffb92014-04-03 14:43:30 -0700141 /**
142 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700143 * Controllers to be returned are injected while setup.
144 * See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
Ray Milkey269ffb92014-04-03 14:43:30 -0700145 * to what controllers are injected using mock {@link ServiceCache}.
146 *
147 * @throws Exception
148 */
149 @Test
150 public void testGetAllControllers() throws Exception {
151 String controllerIdRegistered = "controller1";
152 String controllerIdNotRegistered = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700153
Ray Milkey269ffb92014-04-03 14:43:30 -0700154 try {
155 Collection<String> ctrls = registry.getAllControllers();
156 assertTrue(ctrls.contains(controllerIdRegistered));
157 assertFalse(ctrls.contains(controllerIdNotRegistered));
158 } catch (RegistryException e) {
159 e.printStackTrace();
160 fail(e.getMessage());
161 }
162 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700163
Ray Milkey269ffb92014-04-03 14:43:30 -0700164 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700165 * Test if {@link ZookeeperRegistry#requestControl(long, IControllerRegistryService.ControlChangeCallback)}
166 * correctly take control of specific switch.
167 * Because {@link ZookeeperRegistry#requestControl(long, IControllerRegistryService.ControlChangeCallback)}
Ray Milkey269ffb92014-04-03 14:43:30 -0700168 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
169 *
170 * @throws Exception
171 */
172 @Test
173 public void testRequestControl() throws Exception {
174 // Mock LeaderLatch
175 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
176 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
177 EasyMock.expectLastCall().once();
178 latch.start();
179 EasyMock.expectLastCall().once();
180 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700181
Ray Milkey269ffb92014-04-03 14:43:30 -0700182 PowerMock.expectNew(LeaderLatch.class,
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700183 EasyMock.anyObject(CuratorFramework.class),
184 EasyMock.anyObject(String.class),
185 EasyMock.anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700186 .andReturn(latch).once();
187 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700188
Ray Milkey269ffb92014-04-03 14:43:30 -0700189 String controllerId = "controller2013";
190 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700191
Ray Milkey269ffb92014-04-03 14:43:30 -0700192 LoggingCallback callback = new LoggingCallback(1);
193 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700194
Ray Milkey269ffb92014-04-03 14:43:30 -0700195 try {
196 registry.requestControl(dpidToRequest, callback);
197 } catch (RegistryException e) {
198 e.printStackTrace();
199 fail(e.getMessage());
200 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700201
Ray Milkey269ffb92014-04-03 14:43:30 -0700202 EasyMock.verify(latch);
203 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700204
Ray Milkey269ffb92014-04-03 14:43:30 -0700205 /**
206 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
207 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
208 * {@link LeaderLatch} object and verify latch is correctly set up.
209 *
210 * @throws Exception
211 */
212 @Test
213 public void testReleaseControl() throws Exception {
214 // Mock of LeaderLatch
215 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
216 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
217 EasyMock.expectLastCall().once();
218 latch.start();
219 EasyMock.expectLastCall().once();
220 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
221 EasyMock.expectLastCall().once();
222 latch.close();
223 EasyMock.expectLastCall().once();
224 EasyMock.replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700225
Ray Milkey269ffb92014-04-03 14:43:30 -0700226 PowerMock.expectNew(LeaderLatch.class,
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700227 EasyMock.anyObject(CuratorFramework.class),
228 EasyMock.anyObject(String.class),
229 EasyMock.anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700230 .andReturn(latch).once();
231 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700232
Ray Milkey269ffb92014-04-03 14:43:30 -0700233 String controllerId = "controller2013";
234 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700235
Ray Milkey269ffb92014-04-03 14:43:30 -0700236 long dpidToRequest = 2000L;
237 LoggingCallback callback = new LoggingCallback(1);
238
239 registry.requestControl(dpidToRequest, callback);
240 registry.releaseControl(dpidToRequest);
241
242 EasyMock.verify(latch);
243 }
244
245 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700246 * Test if {@link ZookeeperRegistry#hasControl(long)} returns
247 * correct status whether controller has control of specific switch.
Ray Milkey269ffb92014-04-03 14:43:30 -0700248 *
249 * @throws Exception
250 */
251 @Test
252 public void testHasControl() throws Exception {
253 // Mock of LeaderLatch
254 LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
255 latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
256 EasyMock.expectLastCall().once();
257 latch.start();
258 EasyMock.expectLastCall().once();
259 EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
260 latch.removeListener(EasyMock.anyObject(SwitchLeaderListener.class));
261 EasyMock.expectLastCall().once();
262 latch.close();
263 EasyMock.expectLastCall().once();
264 EasyMock.replay(latch);
265
266 PowerMock.expectNew(LeaderLatch.class,
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700267 EasyMock.anyObject(CuratorFramework.class),
268 EasyMock.anyObject(String.class),
269 EasyMock.anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700270 .andReturn(latch);
271 PowerMock.replay(LeaderLatch.class);
272
273 String controllerId = "controller2013";
274 registry.registerController(controllerId);
275
276 long dpidToRequest = 2000L;
277 LoggingCallback callback = new LoggingCallback(2);
278
279 // Test before request control
280 assertFalse(registry.hasControl(dpidToRequest));
281
282 registry.requestControl(dpidToRequest, callback);
283
284 // Test after request control
285 assertTrue(registry.hasControl(dpidToRequest));
286
287 registry.releaseControl(dpidToRequest);
288
289 // Test after release control
290 assertFalse(registry.hasControl(dpidToRequest));
291
292 EasyMock.verify(latch);
293 }
294
295 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700296 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)}
297 * correctly returns controller ID of specific switch.
298 * Relation between controllers and switches are defined by
299 * {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Ray Milkey269ffb92014-04-03 14:43:30 -0700300 *
301 * @throws Throwable
302 */
303 @Test
304 public void testGetControllerForSwitch() throws Throwable {
305 long dpidRegistered = 1000L;
306 long dpidNotRegistered = 2000L;
307
308 setPathChildrenCache();
309
310 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
311 assertEquals("controller1", controllerForSw);
312
313 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
314 assertEquals(null, controllerForSw);
315 }
316
317 /**
318 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
319 * switches controlled by a controller.
320 *
321 * @throws Exception
322 */
323 // TODO: Test after getSwitchesControlledByController() is implemented.
324 @Ignore
325 @Test
326 public void testGetSwitchesControlledByController() throws Exception {
327 String controllerIdRegistered = "controller1";
328 String dpidRegistered = HexString.toHexString(1000L);
329 String controllerIdNotRegistered = CONTROLLER_ID;
330
331 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
332 assertNotNull(switches);
333 assertTrue(switches.contains(dpidRegistered));
334
335 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
336 assertNotNull(switches);
337 assertEquals(0, switches.size());
338 }
339
340 /**
341 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
342 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
343 *
344 * @throws Exception
345 */
346 @Test
347 public void testGetAllSwitches() throws Exception {
348 String[] dpids = {
349 HexString.toHexString(1000L),
350 HexString.toHexString(1001L),
351 HexString.toHexString(1002L),
352 };
353
354 setPathChildrenCache();
355
356 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
357 assertNotNull(switches);
358 assertEquals(dpids.length, switches.size());
359 for (String dpid : dpids) {
360 assertTrue(switches.keySet().contains(dpid));
361 }
362 }
363
364 /**
365 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
366 */
367 @Test
368 public void testAllocateUniqueIdBlock() {
369 // Number of blocks to be verified that any of them has unique block
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700370 final int numBlocks = 100;
371 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(numBlocks);
Ray Milkey269ffb92014-04-03 14:43:30 -0700372
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700373 for (int i = 0; i < numBlocks; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700374 IdBlock block = registry.allocateUniqueIdBlock();
375 assertNotNull(block);
376 blocks.add(block);
377 }
378
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700379 for (int i = 0; i < numBlocks; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700380 IdBlock block1 = blocks.get(i);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700381 for (int j = i + 1; j < numBlocks; ++j) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700382 IdBlock block2 = blocks.get(j);
383 IdBlock lower, higher;
384
385 if (block1.getStart() < block2.getStart()) {
386 lower = block1;
387 higher = block2;
388 } else {
389 lower = block2;
390 higher = block1;
391 }
392
393 assertTrue(lower.getSize() > 0L);
394 assertTrue(higher.getSize() > 0L);
395 assertTrue(lower.getEnd() <= higher.getStart());
396 }
397 }
398 }
399
400
401 //-------------------------- Creation of mock objects --------------------------
402
403 /**
404 * Create mock {@link CuratorFramework} object with initial value below.<br>
405 * [Ctrl ID] : [DPID]<br>
406 * controller1 : 1000<br>
407 * controller2 : 1001<br>
408 * controller2 : 1002<br>
409 * controller2013 : nothing
410 *
411 * @return Created mock object
412 * @throws Exception
413 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700414 @SuppressWarnings({"serial", "unchecked" })
Ray Milkey269ffb92014-04-03 14:43:30 -0700415 private CuratorFramework createCuratorFrameworkMock() throws Exception {
416 // Mock of AtomicValue
417 AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
418 EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
419 EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
420 private long value = 0;
421
422 @Override
423 public Long answer() throws Throwable {
424 value += ID_BLOCK_SIZE;
425 return value;
426 }
427 }).anyTimes();
428 EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
429 private long value = ID_BLOCK_SIZE;
430
431 @Override
432 public Long answer() throws Throwable {
433 value += ID_BLOCK_SIZE;
434 return value;
435 }
436 }).anyTimes();
437 EasyMock.replay(atomicValue);
438
439 // Mock DistributedAtomicLong
440 DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
441 EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
442 EasyMock.replay(daLong);
443 PowerMock.expectNew(DistributedAtomicLong.class,
444 new Class<?>[]{CuratorFramework.class, String.class, RetryPolicy.class},
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700445 EasyMock.anyObject(CuratorFramework.class),
446 EasyMock.anyObject(String.class),
447 EasyMock.anyObject(RetryPolicy.class)).
Ray Milkey269ffb92014-04-03 14:43:30 -0700448 andReturn(daLong).anyTimes();
449 PowerMock.replay(DistributedAtomicLong.class);
450
451 // Mock ListenerContainer
452 ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
453 listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
454 EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
455 @Override
456 public Object answer() throws Throwable {
457 pathChildrenCacheListener = (PathChildrenCacheListener) EasyMock.getCurrentArguments()[0];
458 return null;
459 }
460 }).once();
461 EasyMock.replay(listenerContainer);
462
463 // Mock PathChildrenCache
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700464 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(
465 CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
466 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1",
467 new String[] {HexString.toHexString(1000L)}, listenerContainer);
468 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2",
469 new String[] {
470 HexString.toHexString(1001L), HexString.toHexString(1002L)},
471 listenerContainer);
Ray Milkey269ffb92014-04-03 14:43:30 -0700472
473 // Mock PathChildrenCache constructor
474 PowerMock.expectNew(PathChildrenCache.class,
475 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
476 andReturn(pathChildrenCacheMain).once();
477 PowerMock.expectNew(PathChildrenCache.class,
478 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
479 andReturn(pathChildrenCache1).once();
480 PowerMock.expectNew(PathChildrenCache.class,
481 EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
482 andReturn(pathChildrenCache2).anyTimes();
483 PowerMock.replay(PathChildrenCache.class);
484
485 // Mock ServiceCache
486 ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
487 serviceCache.start();
488 EasyMock.expectLastCall().once();
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700489 EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService>>() { {
Ray Milkey269ffb92014-04-03 14:43:30 -0700490 add(createServiceInstanceMock("controller1"));
491 add(createServiceInstanceMock("controller2"));
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700492 } }).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700493 EasyMock.replay(serviceCache);
494
495 // Mock ServiceCacheBuilder
496 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700497 EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class)))
498 .andReturn(serviceCacheBuilder).once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700499 EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
500 EasyMock.replay(serviceCacheBuilder);
501
502 // Mock ServiceDiscovery
503 ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
504 serviceDiscovery.start();
505 EasyMock.expectLastCall().once();
506 EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
507 serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
508 EasyMock.expectLastCall().once();
509 EasyMock.replay(serviceDiscovery);
510
511 // Mock CuratorFramework
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700512 CuratorFramework mockClient = EasyMock.createMock(CuratorFramework.class);
513 mockClient.start();
Ray Milkey269ffb92014-04-03 14:43:30 -0700514 EasyMock.expectLastCall().once();
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700515 EasyMock.expect(mockClient.usingNamespace(EasyMock.anyObject(String.class))).andReturn(mockClient);
516 EasyMock.replay(mockClient);
Ray Milkey269ffb92014-04-03 14:43:30 -0700517
518 // Mock ServiceDiscoveryBuilder
519 ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700520 EasyMock.expect(builder.client(mockClient)).andReturn(builder).once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700521 EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
522 EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
523 EasyMock.replay(builder);
524
525 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
526 EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
527 PowerMock.replay(ServiceDiscoveryBuilder.class);
528
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700529 return mockClient;
Ray Milkey269ffb92014-04-03 14:43:30 -0700530 }
531
532 /**
533 * Create mock {@link ServiceInstance} object using given controller ID.
534 *
535 * @param controllerId Controller ID to represent instance's payload (ControllerService).
536 * @return Mock ServiceInstance object
537 */
538 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
539 ControllerService controllerService = EasyMock.createMock(ControllerService.class);
540 EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
541 EasyMock.replay(controllerService);
542
543 @SuppressWarnings("unchecked")
544 ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
545 EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
546 EasyMock.replay(serviceInstance);
547
548 return serviceInstance;
549 }
550
551 /**
552 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
553 *
554 * @param controllerId Controller ID to represent current data.
555 * @param paths List of HexString indicating switch's DPID.
556 * @param listener Callback object to be set as Listenable.
557 * @return Mock PathChildrenCache object
558 * @throws Exception
559 */
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700560 private PathChildrenCache createPathChildrenCacheMock(
561 final String controllerId,
562 final String[] paths,
563 ListenerContainer<PathChildrenCacheListener> listener)
564 throws Exception {
Ray Milkey269ffb92014-04-03 14:43:30 -0700565 PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
566
567 EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
568
569 pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
570 EasyMock.expectLastCall().anyTimes();
571
572 List<ChildData> childs = new ArrayList<ChildData>();
573 for (String path : paths) {
574 childs.add(createChildDataMockForCurrentData(controllerId, path));
575 }
576 EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
577
578 pathChildrenCache.rebuild();
579 EasyMock.expectLastCall().anyTimes();
580
581 EasyMock.replay(pathChildrenCache);
582
583 return pathChildrenCache;
584 }
585
586 /**
587 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
588 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
589 *
590 * @param controllerId Controller ID
591 * @param path HexString indicating switch's DPID
592 * @return Mock ChildData object
593 */
594 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
595 ChildData data = EasyMock.createMock(ChildData.class);
596 EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
597 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
598 EasyMock.replay(data);
599
600 return data;
601 }
602
603 /**
604 * Inject relations between controllers and switches using callback object.
605 *
606 * @throws Exception
607 */
608 private void setPathChildrenCache() throws Exception {
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700609 pathChildrenCacheListener.childEvent(
610 client,
611 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L),
612 PathChildrenCacheEvent.Type.CHILD_ADDED));
613 pathChildrenCacheListener.childEvent(
614 client,
615 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L),
616 PathChildrenCacheEvent.Type.CHILD_ADDED));
617 pathChildrenCacheListener.childEvent(
618 client,
619 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L),
620 PathChildrenCacheEvent.Type.CHILD_ADDED));
Ray Milkey269ffb92014-04-03 14:43:30 -0700621 }
622
623 /**
624 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
625 *
626 * @param controllerId Controller ID.
627 * @param path HexString of DPID.
628 * @param type Event type to be set to mock object.
629 * @return Mock PathChildrenCacheEvent object
630 */
631 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
632 PathChildrenCacheEvent.Type type) {
633 PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
634 ChildData data = EasyMock.createMock(ChildData.class);
635
636 EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
637 EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
638 EasyMock.replay(data);
639
640 EasyMock.expect(event.getType()).andReturn(type).anyTimes();
641 EasyMock.expect(event.getData()).andReturn(data).anyTimes();
642 EasyMock.replay(event);
643
644 return event;
645 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700646}