blob: a8ea8e11fa569419a1e11927cd1d130d3160f37a [file] [log] [blame]
Jonathan Hartdeda0ba2014-04-03 11:14:12 -07001package net.onrc.onos.core.registry;
Naoki Shiotad00accf2013-06-25 14:40:37 -07002
Jonathan Harta88fd242014-04-03 11:24:54 -07003import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertFalse;
5import static org.junit.Assert.assertNotEquals;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertNull;
8import static org.junit.Assert.assertTrue;
9import static org.junit.Assert.fail;
Naoki Shiotad00accf2013-06-25 14:40:37 -070010
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.Map;
16import java.util.concurrent.CountDownLatch;
17import java.util.concurrent.TimeUnit;
18
19import net.floodlightcontroller.core.module.FloodlightModuleContext;
Jonathan Hartdeda0ba2014-04-03 11:14:12 -070020import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
Naoki Shiotad00accf2013-06-25 14:40:37 -070021
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Ignore;
25import org.junit.Test;
26import org.openflow.util.HexString;
27
28/**
Naoki Shiotaa3b2dfa2013-06-27 13:52:24 -070029 * Unit test for {@link StandaloneRegistry}.
Naoki Shiotad00accf2013-06-25 14:40:37 -070030 *
Ray Milkey269ffb92014-04-03 14:43:30 -070031 * @author Naoki Shiota
Naoki Shiotad00accf2013-06-25 14:40:37 -070032 */
33public class StandaloneRegistryTest {
Ray Milkey269ffb92014-04-03 14:43:30 -070034 protected static final long TIMEOUT_MSEC = 1000;
Naoki Shiotad00accf2013-06-25 14:40:37 -070035
Ray Milkey269ffb92014-04-03 14:43:30 -070036 protected StandaloneRegistry registry;
Naoki Shiotad00accf2013-06-25 14:40:37 -070037
Ray Milkey269ffb92014-04-03 14:43:30 -070038 /**
39 * Implementation of {@link ControlChangeCallback} which defines callback interfaces called by Registry.
40 * This class remembers past callback parameters and provides methods to access them.
41 * This class also provides CountDownLatch so one can wait until the callback be called
42 * specific times (specified by constructor parameter). Particularly, the first time callback
43 * called is supposed for registration, this class has an independent latch to wait for
44 * the first callback.
45 *
46 * @author Naoki Shiota
47 */
48 public static class LoggingCallback implements ControlChangeCallback {
49 private LinkedList<Long> dpidsCalledback = new LinkedList<Long>();
50 private LinkedList<Boolean> controlsCalledback = new LinkedList<Boolean>();
51 private CountDownLatch lock = null, registerLock = null;
52 ;
53
54 /**
55 * Constructor with number of times callback to be called.
56 *
57 * @param numberToCall Number of times expected callback to be called
58 */
59 public LoggingCallback(int numberToCall) {
60 lock = new CountDownLatch(numberToCall);
61 registerLock = new CountDownLatch(1);
62 }
63
64 /**
65 * Wait until registration is finished (callback is called for the first time).
66 *
67 * @throws InterruptedException
68 */
69 public void waitForRegistration() throws InterruptedException {
70 registerLock.await();
71 }
72
73 /**
74 * Wait for registration specifying timeout.
75 *
76 * @param msec Milliseconds to timeout
77 * @throws InterruptedException
78 */
79 public void waitForRegistration(long msec) throws InterruptedException {
80 registerLock.await(msec, TimeUnit.MILLISECONDS);
81 }
82
83 /**
84 * Wait until callback is called specific times.
85 *
86 * @throws InterruptedException
87 */
88 public void waitUntilCalled() throws InterruptedException {
89 lock.await();
90 }
91
92 /**
93 * Wait until callback is called specific times, specifying timeout.
94 *
95 * @param msec Milliseconds to timeout
96 * @throws InterruptedException
97 */
98 public void waitUntilCalled(long msec) throws InterruptedException {
99 lock.await(msec, TimeUnit.MILLISECONDS);
100 }
101
102 /**
103 * Get DPID parameter given by specific callback time.
104 *
105 * @param index Specify which time to get parameter
106 * @return DPID value by number.
107 */
108 public Long getDpid(int index) {
109 return dpidsCalledback.get(index);
110 }
111
112 /**
113 * Get hasControl parameter given by specific callback time.
114 *
115 * @param index Specify which time to get parameter
116 * @return hasControl value
117 */
118 public Boolean getControl(int index) {
119 return controlsCalledback.get(index);
120 }
121
122 /**
123 * Get DPID parameter given by latest call.
124 *
125 * @return DPID value by number
126 */
127 public Long getLatestDpid() {
128 return dpidsCalledback.peekLast();
129 }
130
131 /**
132 * Get hasControl parameter given by latest call
133 *
134 * @return hasControl value
135 */
136 public Boolean getLatestControl() {
137 return controlsCalledback.peekLast();
138 }
139
140 @Override
141 public void controlChanged(long dpid, boolean hasControl) {
142 dpidsCalledback.addLast(dpid);
143 controlsCalledback.addLast(hasControl);
144
145 lock.countDown();
146 registerLock.countDown();
147 }
148 }
149
150 ;
151
152 @Before
153 public void setUp() throws Exception {
Naoki Shiotad00accf2013-06-25 14:40:37 -0700154 FloodlightModuleContext fmc = new FloodlightModuleContext();
Ray Milkey269ffb92014-04-03 14:43:30 -0700155 registry = new StandaloneRegistry();
156 registry.init(fmc);
157 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700158
Ray Milkey269ffb92014-04-03 14:43:30 -0700159 @After
160 public void tearDown() {
161 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700162
Ray Milkey269ffb92014-04-03 14:43:30 -0700163 /**
164 * Test if {@link StandaloneRegistry#registerController(String)} can run without error.
165 */
166 @Test
167 public void testRegisterController() {
168 String controllerIdToRegister = "test";
169 try {
170 registry.registerController(controllerIdToRegister);
171 } catch (RegistryException e) {
172 e.printStackTrace();
173 fail(e.getMessage());
174 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700175
Ray Milkey269ffb92014-04-03 14:43:30 -0700176 // Register Controller ID doubly
177 try {
178 registry.registerController(controllerIdToRegister);
179 fail("Double registration goes through without exception");
180 } catch (RegistryException e) {
181 // expected behavior
182 }
183 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700184
Ray Milkey269ffb92014-04-03 14:43:30 -0700185 /**
186 * Test if {@link StandaloneRegistry#getControllerId()} can return correct ID.
187 *
188 * @throws RegistryException
189 */
190 @Test
191 public void testGetControllerId() throws RegistryException {
192 String controllerIdToRegister = "test";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700193
Ray Milkey269ffb92014-04-03 14:43:30 -0700194 // try before controller is registered
195 String controllerId = registry.getControllerId();
196 assertNull(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700197
Ray Milkey269ffb92014-04-03 14:43:30 -0700198 // register
199 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700200
Ray Milkey269ffb92014-04-03 14:43:30 -0700201 // call getControllerId and verify
202 controllerId = registry.getControllerId();
203 assertNotNull(controllerId);
204 assertEquals(controllerIdToRegister, controllerId);
205 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700206
Ray Milkey269ffb92014-04-03 14:43:30 -0700207 /**
208 * Test if {@link StandaloneRegistry#getAllControllers()} can return correct list of controllers.
209 *
210 * @throws RegistryException
211 */
212 @Test
213 public void testGetAllControllers() throws RegistryException {
214 String controllerIdToRegister = "test";
Naoki Shiotad00accf2013-06-25 14:40:37 -0700215
Ray Milkey269ffb92014-04-03 14:43:30 -0700216 // Test before register controller
217 try {
218 Collection<String> ctrls = registry.getAllControllers();
219 assertFalse(ctrls.contains(controllerIdToRegister));
220 } catch (RegistryException e) {
221 e.printStackTrace();
222 fail(e.getMessage());
223 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700224
Ray Milkey269ffb92014-04-03 14:43:30 -0700225 // register
226 registry.registerController(controllerIdToRegister);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700227
Ray Milkey269ffb92014-04-03 14:43:30 -0700228 // Test after register controller
229 try {
230 Collection<String> ctrls = registry.getAllControllers();
231 assertTrue(ctrls.contains(controllerIdToRegister));
232 } catch (RegistryException e) {
233 e.printStackTrace();
234 fail(e.getMessage());
235 }
236 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700237
Ray Milkey269ffb92014-04-03 14:43:30 -0700238 /**
239 * Test if {@link StandaloneRegistry#requestControl(long, ControlChangeCallback)} can correctly take control for switch so that callback is called.
240 *
241 * @throws RegistryException
242 * @throws InterruptedException
243 */
244 @Test
245 public void testRequestControl() throws InterruptedException, RegistryException {
246 String controllerId = "test";
247 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700248
Ray Milkey269ffb92014-04-03 14:43:30 -0700249 LoggingCallback callback = new LoggingCallback(1);
250 long dpidToRequest = 1000L;
Naoki Shiotad00accf2013-06-25 14:40:37 -0700251
Ray Milkey269ffb92014-04-03 14:43:30 -0700252 try {
253 registry.requestControl(dpidToRequest, callback);
254 } catch (RegistryException e) {
255 e.printStackTrace();
256 fail(e.getMessage());
257 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700258
Ray Milkey269ffb92014-04-03 14:43:30 -0700259 callback.waitForRegistration();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700260
Ray Milkey269ffb92014-04-03 14:43:30 -0700261 long dpidCallback = callback.getLatestDpid();
262 boolean controlCallback = callback.getLatestControl();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700263
Ray Milkey269ffb92014-04-03 14:43:30 -0700264 assertEquals(dpidToRequest, dpidCallback);
265 assertTrue(controlCallback);
266 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700267
Ray Milkey269ffb92014-04-03 14:43:30 -0700268 /**
269 * Test if {@link StandaloneRegistry#releaseControl(long)} can correctly release the control so that callback is called.
270 *
271 * @throws InterruptedException
272 * @throws RegistryException
273 */
274 @Test
275 public void testReleaseControl() throws InterruptedException, RegistryException {
276 String controllerId = "test";
277 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700278
Ray Milkey269ffb92014-04-03 14:43:30 -0700279 long dpidToRequest = 1000L;
280 LoggingCallback callback = new LoggingCallback(2);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700281
Ray Milkey269ffb92014-04-03 14:43:30 -0700282 // to request and wait to take control
283 registry.requestControl(dpidToRequest, callback);
284 callback.waitForRegistration();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700285
Ray Milkey269ffb92014-04-03 14:43:30 -0700286 registry.releaseControl(dpidToRequest);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700287
Ray Milkey269ffb92014-04-03 14:43:30 -0700288 // verify
289 callback.waitUntilCalled();
290 assertEquals(dpidToRequest, (long) callback.getLatestDpid());
291 assertFalse(callback.getLatestControl());
292 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700293
Ray Milkey269ffb92014-04-03 14:43:30 -0700294 /**
295 * Test if {@link StandaloneRegistry#hasControl(long)} returns correct status.
296 *
297 * @throws InterruptedException
298 * @throws RegistryException
299 */
300 @Test
301 public void testHasControl() throws InterruptedException, RegistryException {
302 String controllerId = "test";
303 registry.registerController(controllerId);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700304
Ray Milkey269ffb92014-04-03 14:43:30 -0700305 long dpidToRequest = 1000L;
306 LoggingCallback callback = new LoggingCallback(2);
Naoki Shiotad00accf2013-06-25 14:40:37 -0700307
Ray Milkey269ffb92014-04-03 14:43:30 -0700308 // Test before request control
309 assertFalse(registry.hasControl(dpidToRequest));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700310
Ray Milkey269ffb92014-04-03 14:43:30 -0700311 registry.requestControl(dpidToRequest, callback);
312 callback.waitForRegistration();
Naoki Shiotad00accf2013-06-25 14:40:37 -0700313
Ray Milkey269ffb92014-04-03 14:43:30 -0700314 // Test after take control
315 assertTrue(registry.hasControl(dpidToRequest));
Naoki Shiotad00accf2013-06-25 14:40:37 -0700316
Ray Milkey269ffb92014-04-03 14:43:30 -0700317 registry.releaseControl(dpidToRequest);
318
319 callback.waitUntilCalled();
320
321 // Test after release control
322 assertFalse(registry.hasControl(dpidToRequest));
323 }
324
325 /**
326 * Test if {@link StandaloneRegistry#getControllerForSwitch(long)} returns correct controller ID.
327 *
328 * @throws InterruptedException
329 * @throws RegistryException
330 */
331 @Test
332 public void testGetControllerForSwitch() throws InterruptedException, RegistryException {
333 String controllerId = "test";
334 registry.registerController(controllerId);
335
336 long dpidToRequest = 1000L;
337 LoggingCallback callback = new LoggingCallback(2);
338
339 // Test before request control
340 try {
341 String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
342 assertNotEquals(controllerId, controllerForSw);
343 } catch (RegistryException e) {
344 fail("Failed before request control : " + e.getMessage());
345 e.printStackTrace();
346 }
347
348 registry.requestControl(dpidToRequest, callback);
349 callback.waitForRegistration();
350
351 // Test after take control
352 try {
353 String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
354 assertEquals(controllerId, controllerForSw);
355 } catch (RegistryException e) {
356 fail("Failed after take control : " + e.getMessage());
357 e.printStackTrace();
358 }
359
360 registry.releaseControl(dpidToRequest);
361 callback.waitUntilCalled();
362
363 // Test after release control
364 try {
365 String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
366 assertNotEquals(controllerId, controllerForSw);
367 } catch (RegistryException e) {
368 fail("Failed after release control : " + e.getMessage());
369 e.printStackTrace();
370 }
371 }
372
373 /**
374 * Test if {@link StandaloneRegistry#getAllSwitches()} returns correct list of switches.
375 *
376 * @throws InterruptedException
377 * @throws RegistryException
378 */
379 @Test
380 public void testGetAllSwitches() throws InterruptedException, RegistryException {
381 String controllerId = "test";
382 registry.registerController(controllerId);
383
384 long dpidToRequest = 1000L;
385 String dpidToRequestStr = HexString.toHexString(dpidToRequest);
386 LoggingCallback callback = new LoggingCallback(2);
387
388 // Test before request control
389 Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
390 assertNotNull(switches);
391 assertFalse(switches.keySet().contains(dpidToRequestStr));
392
393 registry.requestControl(dpidToRequest, callback);
394 callback.waitForRegistration();
395
396 // Test after take control
397 switches = registry.getAllSwitches();
398 assertNotNull(switches);
399 assertTrue(switches.keySet().contains(dpidToRequestStr));
400 int count = 0;
401 for (ControllerRegistryEntry ctrl : switches.get(dpidToRequestStr)) {
402 if (ctrl.getControllerId().equals(controllerId)) {
403 ++count;
404 }
405 }
406 assertEquals(1, count);
407
408 registry.releaseControl(dpidToRequest);
409 callback.waitUntilCalled();
410
411 // Test after release control
412 switches = registry.getAllSwitches();
413 assertNotNull(switches);
414 assertFalse(switches.keySet().contains(dpidToRequestStr));
415 }
416
417 /**
418 * Test if {@link StandaloneRegistry#getSwitchesControlledByController(String)} returns correct list of switches.
419 *
420 * @throws InterruptedException
421 * @throws RegistryException
422 */
423 // TODO: remove @Ignore after implement StandaloneRegistry#getSwitchesControlledByController
424 @Ignore
425 @Test
426 public void testGetSwitchesControlledByController() throws InterruptedException, RegistryException {
427 String controllerId = "test";
428 registry.registerController(controllerId);
429
430 long dpidToRequest = 1000L;
431 String dpidToRequestStr = HexString.toHexString(dpidToRequest);
432 LoggingCallback callback = new LoggingCallback(2);
433
434 // Test before request control
435 Collection<Long> switches = registry.getSwitchesControlledByController(controllerId);
436 assertNotNull(switches);
437 assertFalse(switches.contains(dpidToRequestStr));
438
439 registry.requestControl(dpidToRequest, callback);
440 callback.waitForRegistration();
441
442 // Test after take control
443 switches = registry.getSwitchesControlledByController(controllerId);
444 assertNotNull(switches);
445 assertTrue(switches.contains(dpidToRequestStr));
446 int count = 0;
447 for (Long dpid : switches) {
448 if ((long) dpid == dpidToRequest) {
449 ++count;
450 }
451 }
452 assertEquals(1, count);
453
454 registry.releaseControl(dpidToRequest);
455 callback.waitUntilCalled();
456
457 // Test after release control
458 switches = registry.getSwitchesControlledByController(controllerId);
459 assertNotNull(switches);
460 assertFalse(switches.contains(dpidToRequestStr));
461 }
462
463 /**
464 * Test if {@link StandaloneRegistry#allocateUniqueIdBlock()} returns appropriate object.
465 * Get bulk of IdBlocks and check if they do have unique range of IDs.
466 */
467 @Test
468 public void testAllocateUniqueIdBlock() {
469 // Number of blocks to be verified that any of them has unique block
470 final int NUM_BLOCKS = 100;
471 ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
472
473 for (int i = 0; i < NUM_BLOCKS; ++i) {
474 blocks.add(registry.allocateUniqueIdBlock());
475 }
476
477 for (int i = 0; i < NUM_BLOCKS; ++i) {
478 IdBlock block1 = blocks.get(i);
479 for (int j = i + 1; j < NUM_BLOCKS; ++j) {
480 IdBlock block2 = blocks.get(j);
481 IdBlock lower, higher;
482
483 if (block1.getStart() < block2.getStart()) {
484 lower = block1;
485 higher = block2;
486 } else {
487 lower = block2;
488 higher = block1;
489 }
490
491 assertTrue(lower.getSize() > 0L);
492 assertTrue(higher.getSize() > 0L);
493 assertTrue(lower.getEnd() < higher.getStart());
494 }
495 }
496 }
Naoki Shiotad00accf2013-06-25 14:40:37 -0700497}