blob: e6e4e72fe407bea86c963fea90b320a7254320c7 [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;
Sho SHIMIZUfc932d52014-08-15 11:22:37 -070012import net.onrc.onos.core.util.IdBlock;
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -070013import net.onrc.onos.core.util.OnosInstanceId;
Naoki Shiotad00accf2013-06-25 14:40:37 -070014
Jonathan Hart116b1fe2014-03-14 18:53:47 -070015import org.apache.curator.RetryPolicy;
16import org.apache.curator.framework.CuratorFramework;
17import org.apache.curator.framework.CuratorFrameworkFactory;
18import org.apache.curator.framework.listen.ListenerContainer;
19import org.apache.curator.framework.recipes.atomic.AtomicValue;
20import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
21import org.apache.curator.framework.recipes.cache.ChildData;
22import org.apache.curator.framework.recipes.cache.PathChildrenCache;
23import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
24import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
25import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
26import org.apache.curator.framework.recipes.leader.LeaderLatch;
27import org.apache.curator.x.discovery.ServiceCache;
28import org.apache.curator.x.discovery.ServiceCacheBuilder;
29import org.apache.curator.x.discovery.ServiceDiscovery;
30import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
31import org.apache.curator.x.discovery.ServiceInstance;
Naoki Shiotad00accf2013-06-25 14:40:37 -070032import 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
Sho SHIMIZU107344e2014-08-13 16:11:53 -070043import static org.easymock.EasyMock.anyBoolean;
44import static org.easymock.EasyMock.anyInt;
45import static org.easymock.EasyMock.anyLong;
46import static org.easymock.EasyMock.anyObject;
47import static org.easymock.EasyMock.createMock;
48import static org.easymock.EasyMock.expect;
49import static org.easymock.EasyMock.expectLastCall;
50import static org.easymock.EasyMock.getCurrentArguments;
51import static org.easymock.EasyMock.replay;
52import static org.easymock.EasyMock.verify;
53
Naoki Shiotad00accf2013-06-25 14:40:37 -070054/**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070055 * Unit test for {@link ZookeeperRegistry}.
56 * NOTE: {@link FloodlightTestCase} conflicts with PowerMock. If FloodLight-related methods need to be tested,
Ray Milkey269ffb92014-04-03 14:43:30 -070057 * implement another test class to test them.
Naoki Shiotad00accf2013-06-25 14:40:37 -070058 */
59@RunWith(PowerMockRunner.class)
60@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
Ray Milkey269ffb92014-04-03 14:43:30 -070061 ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070062 ZookeeperRegistry.SwitchPathCacheListener.class })
Naoki Shiotad00accf2013-06-25 14:40:37 -070063public class ZookeeperRegistryTest extends FloodlightTestCase {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070064 private static final Long ID_BLOCK_SIZE = 0x100000000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -070065
Ray Milkey269ffb92014-04-03 14:43:30 -070066 protected ZookeeperRegistry registry;
67 protected CuratorFramework client;
Naoki Shiotad00accf2013-06-25 14:40:37 -070068
Ray Milkey269ffb92014-04-03 14:43:30 -070069 protected PathChildrenCacheListener pathChildrenCacheListener;
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070070 protected static final String CONTROLLER_ID = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -070071
Ray Milkey269ffb92014-04-03 14:43:30 -070072 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -070073 * Initialize {@link ZookeeperRegistry} Object and inject initial value with
74 * {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
Ray Milkey269ffb92014-04-03 14:43:30 -070075 * This setup code also tests {@link ZookeeperRegistry#init(FloodlightModuleContext)} method itself.
76 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070077 @Override
Ray Milkey269ffb92014-04-03 14:43:30 -070078 @Before
79 public void setUp() throws Exception {
80 super.setUp();
Naoki Shiotad00accf2013-06-25 14:40:37 -070081
Ray Milkey269ffb92014-04-03 14:43:30 -070082 pathChildrenCacheListener = null;
Naoki Shiotad00accf2013-06-25 14:40:37 -070083
Ray Milkey269ffb92014-04-03 14:43:30 -070084 // Mock of CuratorFramework
85 client = createCuratorFrameworkMock();
Naoki Shiotad00accf2013-06-25 14:40:37 -070086
Ray Milkey269ffb92014-04-03 14:43:30 -070087 // Mock of CuratorFrameworkFactory
88 PowerMock.mockStatic(CuratorFrameworkFactory.class);
Sho SHIMIZU107344e2014-08-13 16:11:53 -070089 expect(CuratorFrameworkFactory.newClient((String) anyObject(),
90 anyInt(), anyInt(), (RetryPolicy) anyObject())).andReturn(client);
Ray Milkey269ffb92014-04-03 14:43:30 -070091 PowerMock.replay(CuratorFrameworkFactory.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -070092
Ray Milkey269ffb92014-04-03 14:43:30 -070093 FloodlightModuleContext fmc = new FloodlightModuleContext();
94 registry = new ZookeeperRegistry();
95 fmc.addService(ZookeeperRegistry.class, registry);
Naoki Shiotad00accf2013-06-25 14:40:37 -070096
Ray Milkey269ffb92014-04-03 14:43:30 -070097 registry.init(fmc);
Naoki Shiotad00accf2013-06-25 14:40:37 -070098
Ray Milkey269ffb92014-04-03 14:43:30 -070099 PowerMock.verify(client, CuratorFrameworkFactory.class);
100 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700101
Ray Milkey269ffb92014-04-03 14:43:30 -0700102 /**
103 * Clean up member variables (empty for now).
104 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700105 @Override
Ray Milkey269ffb92014-04-03 14:43:30 -0700106 @After
107 public void tearDown() throws Exception {
108 super.tearDown();
109 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700110
Ray Milkey269ffb92014-04-03 14:43:30 -0700111 /**
112 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700113 * (Exceptions are usually out of test target,
114 * but {@link ZookeeperRegistry#registerController(String)}
115 * throws an exception in case of invalid registration.)
Ray Milkey269ffb92014-04-03 14:43:30 -0700116 */
117 @Test
118 public void testRegisterController() {
119 String controllerIdToRegister = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700120
Ray Milkey269ffb92014-04-03 14:43:30 -0700121 try {
122 registry.registerController(controllerIdToRegister);
123 } catch (RegistryException e) {
124 e.printStackTrace();
125 fail(e.getMessage());
126 }
127 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700128
Ray Milkey269ffb92014-04-03 14:43:30 -0700129 /**
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700130 * Test if {@link ZookeeperRegistry#getOnosInstanceId()} correctly returns
131 * registered ID.
Ray Milkey269ffb92014-04-03 14:43:30 -0700132 *
133 * @throws Exception
134 */
135 @Test
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700136 public void testGetOnosInstanceId() throws Exception {
Ray Milkey269ffb92014-04-03 14:43:30 -0700137 String controllerIdToRegister = "controller1";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700138
Ray Milkey269ffb92014-04-03 14:43:30 -0700139 // try before controller is registered
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700140 OnosInstanceId onosInstanceId = registry.getOnosInstanceId();
141 assertNull(onosInstanceId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700142
Ray Milkey269ffb92014-04-03 14:43:30 -0700143 // register
144 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700145
Pavlin Radoslavov53b208a2014-07-28 13:16:11 -0700146 // call getOnosInstanceId and verify
147 onosInstanceId = registry.getOnosInstanceId();
148 assertNotNull(onosInstanceId);
149 assertEquals(controllerIdToRegister, onosInstanceId.toString());
Ray Milkey269ffb92014-04-03 14:43:30 -0700150 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700151
Ray Milkey269ffb92014-04-03 14:43:30 -0700152 /**
153 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700154 * Controllers to be returned are injected while setup.
155 * See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
Ray Milkey269ffb92014-04-03 14:43:30 -0700156 * to what controllers are injected using mock {@link ServiceCache}.
157 *
158 * @throws Exception
159 */
160 @Test
161 public void testGetAllControllers() throws Exception {
162 String controllerIdRegistered = "controller1";
163 String controllerIdNotRegistered = "controller2013";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700164
Ray Milkey269ffb92014-04-03 14:43:30 -0700165 try {
166 Collection<String> ctrls = registry.getAllControllers();
167 assertTrue(ctrls.contains(controllerIdRegistered));
168 assertFalse(ctrls.contains(controllerIdNotRegistered));
169 } catch (RegistryException e) {
170 e.printStackTrace();
171 fail(e.getMessage());
172 }
173 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700174
Ray Milkey269ffb92014-04-03 14:43:30 -0700175 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700176 * Test if {@link ZookeeperRegistry#requestControl(long, IControllerRegistryService.ControlChangeCallback)}
177 * correctly take control of specific switch.
178 * Because {@link ZookeeperRegistry#requestControl(long, IControllerRegistryService.ControlChangeCallback)}
Ray Milkey269ffb92014-04-03 14:43:30 -0700179 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
180 *
181 * @throws Exception
182 */
183 @Test
184 public void testRequestControl() throws Exception {
185 // Mock LeaderLatch
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700186 LeaderLatch latch = createMock(LeaderLatch.class);
187 latch.addListener(anyObject(SwitchLeaderListener.class));
188 expectLastCall().once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700189 latch.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700190 expectLastCall().once();
191 replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700192
Ray Milkey269ffb92014-04-03 14:43:30 -0700193 PowerMock.expectNew(LeaderLatch.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700194 anyObject(CuratorFramework.class),
195 anyObject(String.class),
196 anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700197 .andReturn(latch).once();
198 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700199
Ray Milkey269ffb92014-04-03 14:43:30 -0700200 String controllerId = "controller2013";
201 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700202
Ray Milkey269ffb92014-04-03 14:43:30 -0700203 LoggingCallback callback = new LoggingCallback(1);
204 long dpidToRequest = 2000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700205
Ray Milkey269ffb92014-04-03 14:43:30 -0700206 try {
207 registry.requestControl(dpidToRequest, callback);
208 } catch (RegistryException e) {
209 e.printStackTrace();
210 fail(e.getMessage());
211 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700212
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700213 verify(latch);
Ray Milkey269ffb92014-04-03 14:43:30 -0700214 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700215
Ray Milkey269ffb92014-04-03 14:43:30 -0700216 /**
217 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
218 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
219 * {@link LeaderLatch} object and verify latch is correctly set up.
220 *
221 * @throws Exception
222 */
223 @Test
224 public void testReleaseControl() throws Exception {
225 // Mock of LeaderLatch
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700226 LeaderLatch latch = createMock(LeaderLatch.class);
227 latch.addListener(anyObject(SwitchLeaderListener.class));
228 expectLastCall().once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700229 latch.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700230 expectLastCall().once();
231 latch.removeListener(anyObject(SwitchLeaderListener.class));
232 expectLastCall().once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700233 latch.close();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700234 expectLastCall().once();
235 replay(latch);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700236
Ray Milkey269ffb92014-04-03 14:43:30 -0700237 PowerMock.expectNew(LeaderLatch.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700238 anyObject(CuratorFramework.class),
239 anyObject(String.class),
240 anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700241 .andReturn(latch).once();
242 PowerMock.replay(LeaderLatch.class);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700243
Ray Milkey269ffb92014-04-03 14:43:30 -0700244 String controllerId = "controller2013";
245 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700246
Ray Milkey269ffb92014-04-03 14:43:30 -0700247 long dpidToRequest = 2000L;
248 LoggingCallback callback = new LoggingCallback(1);
249
250 registry.requestControl(dpidToRequest, callback);
251 registry.releaseControl(dpidToRequest);
252
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700253 verify(latch);
Ray Milkey269ffb92014-04-03 14:43:30 -0700254 }
255
256 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700257 * Test if {@link ZookeeperRegistry#hasControl(long)} returns
258 * correct status whether controller has control of specific switch.
Ray Milkey269ffb92014-04-03 14:43:30 -0700259 *
260 * @throws Exception
261 */
262 @Test
263 public void testHasControl() throws Exception {
264 // Mock of LeaderLatch
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700265 LeaderLatch latch = createMock(LeaderLatch.class);
266 latch.addListener(anyObject(SwitchLeaderListener.class));
267 expectLastCall().once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700268 latch.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700269 expectLastCall().once();
270 expect(latch.hasLeadership()).andReturn(true).anyTimes();
271 latch.removeListener(anyObject(SwitchLeaderListener.class));
272 expectLastCall().once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700273 latch.close();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700274 expectLastCall().once();
275 replay(latch);
Ray Milkey269ffb92014-04-03 14:43:30 -0700276
277 PowerMock.expectNew(LeaderLatch.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700278 anyObject(CuratorFramework.class),
279 anyObject(String.class),
280 anyObject(String.class))
Ray Milkey269ffb92014-04-03 14:43:30 -0700281 .andReturn(latch);
282 PowerMock.replay(LeaderLatch.class);
283
284 String controllerId = "controller2013";
285 registry.registerController(controllerId);
286
287 long dpidToRequest = 2000L;
288 LoggingCallback callback = new LoggingCallback(2);
289
290 // Test before request control
291 assertFalse(registry.hasControl(dpidToRequest));
292
293 registry.requestControl(dpidToRequest, callback);
294
295 // Test after request control
296 assertTrue(registry.hasControl(dpidToRequest));
297
298 registry.releaseControl(dpidToRequest);
299
300 // Test after release control
301 assertFalse(registry.hasControl(dpidToRequest));
302
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700303 verify(latch);
Ray Milkey269ffb92014-04-03 14:43:30 -0700304 }
305
306 /**
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700307 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)}
308 * correctly returns controller ID of specific switch.
309 * Relation between controllers and switches are defined by
310 * {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
Ray Milkey269ffb92014-04-03 14:43:30 -0700311 *
312 * @throws Throwable
313 */
314 @Test
315 public void testGetControllerForSwitch() throws Throwable {
316 long dpidRegistered = 1000L;
317 long dpidNotRegistered = 2000L;
318
319 setPathChildrenCache();
320
321 String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
322 assertEquals("controller1", controllerForSw);
323
324 controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
325 assertEquals(null, controllerForSw);
326 }
327
328 /**
329 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
330 * switches controlled by a controller.
331 *
332 * @throws Exception
333 */
334 // TODO: Test after getSwitchesControlledByController() is implemented.
335 @Ignore
336 @Test
337 public void testGetSwitchesControlledByController() throws Exception {
338 String controllerIdRegistered = "controller1";
339 String dpidRegistered = HexString.toHexString(1000L);
340 String controllerIdNotRegistered = CONTROLLER_ID;
341
342 Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
343 assertNotNull(switches);
344 assertTrue(switches.contains(dpidRegistered));
345
346 switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
347 assertNotNull(switches);
348 assertEquals(0, switches.size());
349 }
350
351 /**
352 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
353 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
354 *
355 * @throws Exception
356 */
357 @Test
358 public void testGetAllSwitches() throws Exception {
359 String[] dpids = {
360 HexString.toHexString(1000L),
361 HexString.toHexString(1001L),
362 HexString.toHexString(1002L),
363 };
364
365 setPathChildrenCache();
366
367 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
368 assertNotNull(switches);
369 assertEquals(dpids.length, switches.size());
370 for (String dpid : dpids) {
371 assertTrue(switches.keySet().contains(dpid));
372 }
373 }
374
375 /**
376 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
377 */
378 @Test
379 public void testAllocateUniqueIdBlock() {
380 // Number of blocks to be verified that any of them has unique block
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700381 final int numBlocks = 100;
382 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(numBlocks);
Ray Milkey269ffb92014-04-03 14:43:30 -0700383
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700384 for (int i = 0; i < numBlocks; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700385 IdBlock block = registry.allocateUniqueIdBlock();
386 assertNotNull(block);
387 blocks.add(block);
388 }
389
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700390 for (int i = 0; i < numBlocks; ++i) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700391 IdBlock block1 = blocks.get(i);
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700392 for (int j = i + 1; j < numBlocks; ++j) {
Ray Milkey269ffb92014-04-03 14:43:30 -0700393 IdBlock block2 = blocks.get(j);
394 IdBlock lower, higher;
395
396 if (block1.getStart() < block2.getStart()) {
397 lower = block1;
398 higher = block2;
399 } else {
400 lower = block2;
401 higher = block1;
402 }
403
404 assertTrue(lower.getSize() > 0L);
405 assertTrue(higher.getSize() > 0L);
406 assertTrue(lower.getEnd() <= higher.getStart());
407 }
408 }
409 }
410
411
412 //-------------------------- Creation of mock objects --------------------------
413
414 /**
415 * Create mock {@link CuratorFramework} object with initial value below.<br>
416 * [Ctrl ID] : [DPID]<br>
417 * controller1 : 1000<br>
418 * controller2 : 1001<br>
419 * controller2 : 1002<br>
420 * controller2013 : nothing
421 *
422 * @return Created mock object
423 * @throws Exception
424 */
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700425 @SuppressWarnings({"serial", "unchecked" })
Ray Milkey269ffb92014-04-03 14:43:30 -0700426 private CuratorFramework createCuratorFrameworkMock() throws Exception {
427 // Mock of AtomicValue
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700428 AtomicValue<Long> atomicValue = createMock(AtomicValue.class);
429 expect(atomicValue.succeeded()).andReturn(true).anyTimes();
430 expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700431 private long value = 0;
432
433 @Override
434 public Long answer() throws Throwable {
435 value += ID_BLOCK_SIZE;
436 return value;
437 }
438 }).anyTimes();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700439 expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700440 private long value = ID_BLOCK_SIZE;
441
442 @Override
443 public Long answer() throws Throwable {
444 value += ID_BLOCK_SIZE;
445 return value;
446 }
447 }).anyTimes();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700448 replay(atomicValue);
Ray Milkey269ffb92014-04-03 14:43:30 -0700449
450 // Mock DistributedAtomicLong
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700451 DistributedAtomicLong daLong = createMock(DistributedAtomicLong.class);
452 expect(daLong.add(anyLong())).andReturn(atomicValue).anyTimes();
453 replay(daLong);
Ray Milkey269ffb92014-04-03 14:43:30 -0700454 PowerMock.expectNew(DistributedAtomicLong.class,
455 new Class<?>[]{CuratorFramework.class, String.class, RetryPolicy.class},
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700456 anyObject(CuratorFramework.class),
457 anyObject(String.class),
458 anyObject(RetryPolicy.class)).
Ray Milkey269ffb92014-04-03 14:43:30 -0700459 andReturn(daLong).anyTimes();
460 PowerMock.replay(DistributedAtomicLong.class);
461
462 // Mock ListenerContainer
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700463 ListenerContainer<PathChildrenCacheListener> listenerContainer = createMock(ListenerContainer.class);
464 listenerContainer.addListener(anyObject(PathChildrenCacheListener.class));
465 expectLastCall().andAnswer(new IAnswer<Object>() {
Ray Milkey269ffb92014-04-03 14:43:30 -0700466 @Override
467 public Object answer() throws Throwable {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700468 pathChildrenCacheListener = (PathChildrenCacheListener) getCurrentArguments()[0];
Ray Milkey269ffb92014-04-03 14:43:30 -0700469 return null;
470 }
471 }).once();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700472 replay(listenerContainer);
Ray Milkey269ffb92014-04-03 14:43:30 -0700473
474 // Mock PathChildrenCache
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700475 PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(
476 CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
477 PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1",
478 new String[] {HexString.toHexString(1000L)}, listenerContainer);
479 PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2",
480 new String[] {
481 HexString.toHexString(1001L), HexString.toHexString(1002L)},
482 listenerContainer);
Ray Milkey269ffb92014-04-03 14:43:30 -0700483
484 // Mock PathChildrenCache constructor
485 PowerMock.expectNew(PathChildrenCache.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700486 anyObject(CuratorFramework.class), anyObject(String.class), anyBoolean()).
Ray Milkey269ffb92014-04-03 14:43:30 -0700487 andReturn(pathChildrenCacheMain).once();
488 PowerMock.expectNew(PathChildrenCache.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700489 anyObject(CuratorFramework.class), anyObject(String.class), anyBoolean()).
Ray Milkey269ffb92014-04-03 14:43:30 -0700490 andReturn(pathChildrenCache1).once();
491 PowerMock.expectNew(PathChildrenCache.class,
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700492 anyObject(CuratorFramework.class), anyObject(String.class), anyBoolean()).
Ray Milkey269ffb92014-04-03 14:43:30 -0700493 andReturn(pathChildrenCache2).anyTimes();
494 PowerMock.replay(PathChildrenCache.class);
495
496 // Mock ServiceCache
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700497 ServiceCache<ControllerService> serviceCache = createMock(ServiceCache.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700498 serviceCache.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700499 expectLastCall().once();
500 expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService>>() { {
Ray Milkey269ffb92014-04-03 14:43:30 -0700501 add(createServiceInstanceMock("controller1"));
502 add(createServiceInstanceMock("controller2"));
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700503 } }).anyTimes();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700504 replay(serviceCache);
Ray Milkey269ffb92014-04-03 14:43:30 -0700505
506 // Mock ServiceCacheBuilder
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700507 ServiceCacheBuilder<ControllerService> serviceCacheBuilder = createMock(ServiceCacheBuilder.class);
508 expect(serviceCacheBuilder.name(anyObject(String.class)))
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700509 .andReturn(serviceCacheBuilder).once();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700510 expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
511 replay(serviceCacheBuilder);
Ray Milkey269ffb92014-04-03 14:43:30 -0700512
513 // Mock ServiceDiscovery
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700514 ServiceDiscovery<ControllerService> serviceDiscovery = createMock(ServiceDiscovery.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700515 serviceDiscovery.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700516 expectLastCall().once();
517 expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
518 serviceDiscovery.registerService(anyObject(ServiceInstance.class));
519 expectLastCall().once();
520 replay(serviceDiscovery);
Ray Milkey269ffb92014-04-03 14:43:30 -0700521
522 // Mock CuratorFramework
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700523 CuratorFramework mockClient = createMock(CuratorFramework.class);
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700524 mockClient.start();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700525 expectLastCall().once();
526 expect(mockClient.usingNamespace(anyObject(String.class))).andReturn(mockClient);
527 replay(mockClient);
Ray Milkey269ffb92014-04-03 14:43:30 -0700528
529 // Mock ServiceDiscoveryBuilder
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700530 ServiceDiscoveryBuilder<ControllerService> builder = createMock(ServiceDiscoveryBuilder.class);
531 expect(builder.client(mockClient)).andReturn(builder).once();
532 expect(builder.basePath(anyObject(String.class))).andReturn(builder);
533 expect(builder.build()).andReturn(serviceDiscovery);
534 replay(builder);
Ray Milkey269ffb92014-04-03 14:43:30 -0700535
536 PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700537 expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
Ray Milkey269ffb92014-04-03 14:43:30 -0700538 PowerMock.replay(ServiceDiscoveryBuilder.class);
539
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700540 return mockClient;
Ray Milkey269ffb92014-04-03 14:43:30 -0700541 }
542
543 /**
544 * Create mock {@link ServiceInstance} object using given controller ID.
545 *
546 * @param controllerId Controller ID to represent instance's payload (ControllerService).
547 * @return Mock ServiceInstance object
548 */
549 private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700550 ControllerService controllerService = createMock(ControllerService.class);
551 expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
552 replay(controllerService);
Ray Milkey269ffb92014-04-03 14:43:30 -0700553
554 @SuppressWarnings("unchecked")
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700555 ServiceInstance<ControllerService> serviceInstance = createMock(ServiceInstance.class);
556 expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
557 replay(serviceInstance);
Ray Milkey269ffb92014-04-03 14:43:30 -0700558
559 return serviceInstance;
560 }
561
562 /**
563 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
564 *
565 * @param controllerId Controller ID to represent current data.
566 * @param paths List of HexString indicating switch's DPID.
567 * @param listener Callback object to be set as Listenable.
568 * @return Mock PathChildrenCache object
569 * @throws Exception
570 */
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700571 private PathChildrenCache createPathChildrenCacheMock(
572 final String controllerId,
573 final String[] paths,
574 ListenerContainer<PathChildrenCacheListener> listener)
575 throws Exception {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700576 PathChildrenCache pathChildrenCache = createMock(PathChildrenCache.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700577
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700578 expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700579
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700580 pathChildrenCache.start(anyObject(StartMode.class));
581 expectLastCall().anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700582
583 List<ChildData> childs = new ArrayList<ChildData>();
584 for (String path : paths) {
585 childs.add(createChildDataMockForCurrentData(controllerId, path));
586 }
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700587 expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700588
589 pathChildrenCache.rebuild();
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700590 expectLastCall().anyTimes();
Ray Milkey269ffb92014-04-03 14:43:30 -0700591
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700592 replay(pathChildrenCache);
Ray Milkey269ffb92014-04-03 14:43:30 -0700593
594 return pathChildrenCache;
595 }
596
597 /**
598 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
599 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
600 *
601 * @param controllerId Controller ID
602 * @param path HexString indicating switch's DPID
603 * @return Mock ChildData object
604 */
605 private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700606 ChildData data = createMock(ChildData.class);
607 expect(data.getPath()).andReturn(path + "-0").anyTimes();
608 expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
609 replay(data);
Ray Milkey269ffb92014-04-03 14:43:30 -0700610
611 return data;
612 }
613
614 /**
615 * Inject relations between controllers and switches using callback object.
616 *
617 * @throws Exception
618 */
619 private void setPathChildrenCache() throws Exception {
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700620 pathChildrenCacheListener.childEvent(
621 client,
622 createChildrenCacheEventMock("controller1", HexString.toHexString(1000L),
623 PathChildrenCacheEvent.Type.CHILD_ADDED));
624 pathChildrenCacheListener.childEvent(
625 client,
626 createChildrenCacheEventMock("controller2", HexString.toHexString(1001L),
627 PathChildrenCacheEvent.Type.CHILD_ADDED));
628 pathChildrenCacheListener.childEvent(
629 client,
630 createChildrenCacheEventMock("controller2", HexString.toHexString(1002L),
631 PathChildrenCacheEvent.Type.CHILD_ADDED));
Ray Milkey269ffb92014-04-03 14:43:30 -0700632 }
633
634 /**
635 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
636 *
637 * @param controllerId Controller ID.
638 * @param path HexString of DPID.
639 * @param type Event type to be set to mock object.
640 * @return Mock PathChildrenCacheEvent object
641 */
642 private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
643 PathChildrenCacheEvent.Type type) {
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700644 PathChildrenCacheEvent event = createMock(PathChildrenCacheEvent.class);
645 ChildData data = createMock(ChildData.class);
Ray Milkey269ffb92014-04-03 14:43:30 -0700646
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700647 expect(data.getPath()).andReturn(path).anyTimes();
648 expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
649 replay(data);
Ray Milkey269ffb92014-04-03 14:43:30 -0700650
Sho SHIMIZU107344e2014-08-13 16:11:53 -0700651 expect(event.getType()).andReturn(type).anyTimes();
652 expect(event.getData()).andReturn(data).anyTimes();
653 replay(event);
Ray Milkey269ffb92014-04-03 14:43:30 -0700654
655 return event;
656 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700657}