blob: d62d0bbb8f7a6819a2ca20c2ea54d7a11652a01b [file] [log] [blame]
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -08001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onlab.onos.store.link.impl;
17
18import com.google.common.collect.Iterables;
19
20import org.easymock.Capture;
21import org.junit.After;
22import org.junit.AfterClass;
23import org.junit.Before;
24import org.junit.BeforeClass;
25import org.junit.Ignore;
26import org.junit.Test;
27import org.onlab.onos.cluster.ControllerNode;
28import org.onlab.onos.cluster.DefaultControllerNode;
29import org.onlab.onos.cluster.NodeId;
30import org.onlab.onos.mastership.MastershipTerm;
31import org.onlab.onos.net.ConnectPoint;
32import org.onlab.onos.net.DefaultAnnotations;
33import org.onlab.onos.net.DeviceId;
34import org.onlab.onos.net.Link;
35import org.onlab.onos.net.Link.Type;
36import org.onlab.onos.net.LinkKey;
37import org.onlab.onos.net.PortNumber;
38import org.onlab.onos.net.SparseAnnotations;
39import org.onlab.onos.net.device.DeviceClockService;
40import org.onlab.onos.net.link.DefaultLinkDescription;
41import org.onlab.onos.net.link.LinkDescription;
42import org.onlab.onos.net.link.LinkEvent;
43import org.onlab.onos.net.link.LinkStore;
44import org.onlab.onos.net.link.LinkStoreDelegate;
45import org.onlab.onos.net.provider.ProviderId;
46import org.onlab.onos.store.cluster.StaticClusterService;
47import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
48import org.onlab.onos.store.cluster.messaging.ClusterMessage;
49import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
50import org.onlab.onos.store.cluster.messaging.MessageSubject;
51import org.onlab.onos.store.device.impl.DeviceClockManager;
52import org.onlab.packet.IpAddress;
53
54import java.io.IOException;
55import java.util.HashMap;
56import java.util.Map;
57import java.util.Set;
58import java.util.concurrent.CountDownLatch;
59import java.util.concurrent.TimeUnit;
60
61import static org.easymock.EasyMock.anyObject;
62import static org.easymock.EasyMock.capture;
63import static org.easymock.EasyMock.createNiceMock;
64import static org.easymock.EasyMock.expect;
65import static org.easymock.EasyMock.expectLastCall;
66import static org.easymock.EasyMock.replay;
67import static org.easymock.EasyMock.reset;
68import static org.easymock.EasyMock.verify;
69import static org.junit.Assert.*;
70import static org.onlab.onos.cluster.ControllerNode.State.ACTIVE;
71import static org.onlab.onos.net.DeviceId.deviceId;
72import static org.onlab.onos.net.Link.Type.*;
73import static org.onlab.onos.net.link.LinkEvent.Type.*;
74import static org.onlab.onos.net.NetTestTools.assertAnnotationsEquals;
75
76/**
77 * Test of the GossipLinkStoreTest implementation.
78 */
79public class GossipLinkStoreTest {
80
81 private static final ProviderId PID = new ProviderId("of", "foo");
82 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
83 private static final DeviceId DID1 = deviceId("of:foo");
84 private static final DeviceId DID2 = deviceId("of:bar");
85
86 private static final PortNumber P1 = PortNumber.portNumber(1);
87 private static final PortNumber P2 = PortNumber.portNumber(2);
88 private static final PortNumber P3 = PortNumber.portNumber(3);
89
90 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
91 .set("A1", "a1")
92 .set("B1", "b1")
93 .build();
94 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
95 .remove("A1")
96 .set("B3", "b3")
97 .build();
98 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
99 .set("A2", "a2")
100 .set("B2", "b2")
101 .build();
102 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
103 .remove("A2")
104 .set("B4", "b4")
105 .build();
106
107 // local node
108 private static final NodeId NID1 = new NodeId("local");
109 private static final ControllerNode ONOS1 =
110 new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1"));
111
112 // remote node
113 private static final NodeId NID2 = new NodeId("remote");
114 private static final ControllerNode ONOS2 =
115 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
116
117 private GossipLinkStore linkStoreImpl;
118 private LinkStore linkStore;
119
120 private DeviceClockManager deviceClockManager;
121 private DeviceClockService deviceClockService;
122 private ClusterCommunicationService clusterCommunicator;
123
124
125 @BeforeClass
126 public static void setUpBeforeClass() throws Exception {
127 }
128
129 @AfterClass
130 public static void tearDownAfterClass() throws Exception {
131 }
132
133 @Before
134 public void setUp() throws Exception {
135 deviceClockManager = new DeviceClockManager();
136 deviceClockManager.activate();
137 deviceClockService = deviceClockManager;
138
139 // set initial terms
140 deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1));
141 deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2));
142
143 // TODO mock clusterCommunicator
144 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
145 clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
146 anyObject(ClusterMessageHandler.class));
147 expectLastCall().anyTimes();
148 replay(clusterCommunicator);
149
150 linkStoreImpl = new GossipLinkStore();
151 linkStoreImpl.deviceClockService = deviceClockService;
152 linkStoreImpl.clusterCommunicator = clusterCommunicator;
153 linkStoreImpl.clusterService = new TestClusterService();
154 linkStoreImpl.activate();
155 linkStore = linkStoreImpl;
156
157 verify(clusterCommunicator);
158 reset(clusterCommunicator);
159 }
160
161 @After
162 public void tearDown() throws Exception {
163 linkStoreImpl.deactivate();
164 }
165
166 private void putLink(DeviceId srcId, PortNumber srcNum,
167 DeviceId dstId, PortNumber dstNum, Type type,
168 SparseAnnotations... annotations) {
169 ConnectPoint src = new ConnectPoint(srcId, srcNum);
170 ConnectPoint dst = new ConnectPoint(dstId, dstNum);
171 reset(clusterCommunicator);
172 try {
173 expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class)))
174 .andReturn(true).anyTimes();
175 } catch (IOException e) {
176 fail("Should never reach here");
177 }
178 replay(clusterCommunicator);
179 linkStore.createOrUpdateLink(PID, new DefaultLinkDescription(src, dst, type, annotations));
180 verify(clusterCommunicator);
181 }
182
183 private void resetCommunicatorExpectingNoBroadcast(
184 Capture<ClusterMessage> bcast) {
185 bcast.reset();
186 reset(clusterCommunicator);
187 replay(clusterCommunicator);
188 }
189
190 private void resetCommunicatorExpectingSingleBroadcast(
191 Capture<ClusterMessage> bcast) {
192
193 bcast.reset();
194 reset(clusterCommunicator);
195 try {
196 expect(clusterCommunicator.broadcast(capture(bcast))).andReturn(true).once();
197 } catch (IOException e) {
198 fail("Should never reach here");
199 }
200 replay(clusterCommunicator);
201 }
202
203 private void putLink(LinkKey key, Type type, SparseAnnotations... annotations) {
204 putLink(key.src().deviceId(), key.src().port(),
205 key.dst().deviceId(), key.dst().port(),
206 type, annotations);
207 }
208
209 private static void assertLink(DeviceId srcId, PortNumber srcNum,
210 DeviceId dstId, PortNumber dstNum, Type type,
211 Link link) {
212 assertEquals(srcId, link.src().deviceId());
213 assertEquals(srcNum, link.src().port());
214 assertEquals(dstId, link.dst().deviceId());
215 assertEquals(dstNum, link.dst().port());
216 assertEquals(type, link.type());
217 }
218
219 private static void assertLink(LinkKey key, Type type, Link link) {
220 assertLink(key.src().deviceId(), key.src().port(),
221 key.dst().deviceId(), key.dst().port(),
222 type, link);
223 }
224
225 @Test
226 public final void testGetLinkCount() {
227 assertEquals("initialy empty", 0, linkStore.getLinkCount());
228
229 putLink(DID1, P1, DID2, P2, DIRECT);
230 putLink(DID2, P2, DID1, P1, DIRECT);
231 putLink(DID1, P1, DID2, P2, DIRECT);
232
233 assertEquals("expecting 2 unique link", 2, linkStore.getLinkCount());
234 }
235
236 @Test
237 public final void testGetLinks() {
238 assertEquals("initialy empty", 0,
239 Iterables.size(linkStore.getLinks()));
240
241 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
242 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
243
244 putLink(linkId1, DIRECT);
245 putLink(linkId2, DIRECT);
246 putLink(linkId1, DIRECT);
247
248 assertEquals("expecting 2 unique link", 2,
249 Iterables.size(linkStore.getLinks()));
250
251 Map<LinkKey, Link> links = new HashMap<>();
252 for (Link link : linkStore.getLinks()) {
253 links.put(LinkKey.linkKey(link), link);
254 }
255
256 assertLink(linkId1, DIRECT, links.get(linkId1));
257 assertLink(linkId2, DIRECT, links.get(linkId2));
258 }
259
260 @Test
261 public final void testGetDeviceEgressLinks() {
262 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
263 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
264 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
265
266 putLink(linkId1, DIRECT);
267 putLink(linkId2, DIRECT);
268 putLink(linkId3, DIRECT);
269
270 // DID1,P1 => DID2,P2
271 // DID2,P2 => DID1,P1
272 // DID1,P2 => DID2,P3
273
274 Set<Link> links1 = linkStore.getDeviceEgressLinks(DID1);
275 assertEquals(2, links1.size());
276 // check
277
278 Set<Link> links2 = linkStore.getDeviceEgressLinks(DID2);
279 assertEquals(1, links2.size());
280 assertLink(linkId2, DIRECT, links2.iterator().next());
281 }
282
283 @Test
284 public final void testGetDeviceIngressLinks() {
285 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
286 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
287 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
288
289 putLink(linkId1, DIRECT);
290 putLink(linkId2, DIRECT);
291 putLink(linkId3, DIRECT);
292
293 // DID1,P1 => DID2,P2
294 // DID2,P2 => DID1,P1
295 // DID1,P2 => DID2,P3
296
297 Set<Link> links1 = linkStore.getDeviceIngressLinks(DID2);
298 assertEquals(2, links1.size());
299 // check
300
301 Set<Link> links2 = linkStore.getDeviceIngressLinks(DID1);
302 assertEquals(1, links2.size());
303 assertLink(linkId2, DIRECT, links2.iterator().next());
304 }
305
306 @Test
307 public final void testGetLink() {
308 ConnectPoint src = new ConnectPoint(DID1, P1);
309 ConnectPoint dst = new ConnectPoint(DID2, P2);
310 LinkKey linkId1 = LinkKey.linkKey(src, dst);
311
312 putLink(linkId1, DIRECT);
313
314 Link link = linkStore.getLink(src, dst);
315 assertLink(linkId1, DIRECT, link);
316
317 assertNull("There shouldn't be reverese link",
318 linkStore.getLink(dst, src));
319 }
320
321 @Test
322 public final void testGetEgressLinks() {
323 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
324 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
325 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
326 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
327 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
328
329 putLink(linkId1, DIRECT);
330 putLink(linkId2, DIRECT);
331 putLink(linkId3, DIRECT);
332
333 // DID1,P1 => DID2,P2
334 // DID2,P2 => DID1,P1
335 // DID1,P2 => DID2,P3
336
337 Set<Link> links1 = linkStore.getEgressLinks(d1P1);
338 assertEquals(1, links1.size());
339 assertLink(linkId1, DIRECT, links1.iterator().next());
340
341 Set<Link> links2 = linkStore.getEgressLinks(d2P2);
342 assertEquals(1, links2.size());
343 assertLink(linkId2, DIRECT, links2.iterator().next());
344 }
345
346 @Test
347 public final void testGetIngressLinks() {
348 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
349 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
350 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
351 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
352 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
353
354 putLink(linkId1, DIRECT);
355 putLink(linkId2, DIRECT);
356 putLink(linkId3, DIRECT);
357
358 // DID1,P1 => DID2,P2
359 // DID2,P2 => DID1,P1
360 // DID1,P2 => DID2,P3
361
362 Set<Link> links1 = linkStore.getIngressLinks(d2P2);
363 assertEquals(1, links1.size());
364 assertLink(linkId1, DIRECT, links1.iterator().next());
365
366 Set<Link> links2 = linkStore.getIngressLinks(d1P1);
367 assertEquals(1, links2.size());
368 assertLink(linkId2, DIRECT, links2.iterator().next());
369 }
370
371 @Test
372 public final void testCreateOrUpdateLink() {
373 ConnectPoint src = new ConnectPoint(DID1, P1);
374 ConnectPoint dst = new ConnectPoint(DID2, P2);
375
376 Capture<ClusterMessage> bcast = new Capture<>();
377
378 // add link
379 resetCommunicatorExpectingSingleBroadcast(bcast);
380 final DefaultLinkDescription linkDescription = new DefaultLinkDescription(src, dst, INDIRECT);
381 LinkEvent event = linkStore.createOrUpdateLink(PID,
382 linkDescription);
383 verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, bcast);
384
385 assertLink(DID1, P1, DID2, P2, INDIRECT, event.subject());
386 assertEquals(LINK_ADDED, event.type());
387
388 // update link type
389 resetCommunicatorExpectingSingleBroadcast(bcast);
390 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
391 new DefaultLinkDescription(src, dst, DIRECT));
392 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, bcast);
393
394 assertLink(DID1, P1, DID2, P2, DIRECT, event2.subject());
395 assertEquals(LINK_UPDATED, event2.type());
396
397 // no change
398 resetCommunicatorExpectingSingleBroadcast(bcast);
399 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
400 new DefaultLinkDescription(src, dst, DIRECT));
401 verifyNoBroadcastMessage(bcast);
402
403 assertNull("No change event expected", event3);
404 }
405
406 private void verifyNoBroadcastMessage(Capture<ClusterMessage> bcast) {
407 assertFalse("No broadcast expected", bcast.hasCaptured());
408 }
409
410 private void verifyLinkBroadcastMessage(ProviderId providerId,
411 NodeId sender,
412 ConnectPoint src,
413 ConnectPoint dst,
414 Type type,
415 Capture<ClusterMessage> actualMsg) {
416 verify(clusterCommunicator);
417 assertTrue(actualMsg.hasCaptured());
418 assertEquals(sender, actualMsg.getValue().sender());
419 assertEquals(GossipLinkStoreMessageSubjects.LINK_UPDATE,
420 actualMsg.getValue().subject());
421 InternalLinkEvent linkEvent
422 = GossipLinkStore.SERIALIZER.decode(actualMsg.getValue().payload());
423 assertEquals(providerId, linkEvent.providerId());
424 assertLinkDescriptionEquals(src, dst, type, linkEvent.linkDescription().value());
425
426 }
427
428 private static void assertLinkDescriptionEquals(ConnectPoint src,
429 ConnectPoint dst,
430 Type type,
431 LinkDescription actual) {
432 assertEquals(src, actual.src());
433 assertEquals(dst, actual.dst());
434 assertEquals(type, actual.type());
435 // TODO check annotations
436 }
437
438 @Test
439 public final void testCreateOrUpdateLinkAncillary() {
440 ConnectPoint src = new ConnectPoint(DID1, P1);
441 ConnectPoint dst = new ConnectPoint(DID2, P2);
442
443 Capture<ClusterMessage> bcast = new Capture<>();
444
445 // add Ancillary link
446 resetCommunicatorExpectingSingleBroadcast(bcast);
447 LinkEvent event = linkStore.createOrUpdateLink(PIDA,
448 new DefaultLinkDescription(src, dst, INDIRECT, A1));
449 verifyLinkBroadcastMessage(PIDA, NID1, src, dst, INDIRECT, bcast);
450
451 assertNotNull("Ancillary only link is ignored", event);
452
453 // add Primary link
454 resetCommunicatorExpectingSingleBroadcast(bcast);
455 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
456 new DefaultLinkDescription(src, dst, INDIRECT, A2));
457 verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, bcast);
458
459 assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject());
460 assertAnnotationsEquals(event2.subject().annotations(), A2, A1);
461 assertEquals(LINK_UPDATED, event2.type());
462
463 // update link type
464 resetCommunicatorExpectingSingleBroadcast(bcast);
465 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
466 new DefaultLinkDescription(src, dst, DIRECT, A2));
467 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, bcast);
468
469 assertLink(DID1, P1, DID2, P2, DIRECT, event3.subject());
470 assertAnnotationsEquals(event3.subject().annotations(), A2, A1);
471 assertEquals(LINK_UPDATED, event3.type());
472
473
474 // no change
475 resetCommunicatorExpectingNoBroadcast(bcast);
476 LinkEvent event4 = linkStore.createOrUpdateLink(PID,
477 new DefaultLinkDescription(src, dst, DIRECT));
478 verifyNoBroadcastMessage(bcast);
479
480 assertNull("No change event expected", event4);
481
482 // update link annotation (Primary)
483 resetCommunicatorExpectingSingleBroadcast(bcast);
484 LinkEvent event5 = linkStore.createOrUpdateLink(PID,
485 new DefaultLinkDescription(src, dst, DIRECT, A2_2));
486 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, bcast);
487
488 assertLink(DID1, P1, DID2, P2, DIRECT, event5.subject());
489 assertAnnotationsEquals(event5.subject().annotations(), A2, A2_2, A1);
490 assertEquals(LINK_UPDATED, event5.type());
491
492 // update link annotation (Ancillary)
493 resetCommunicatorExpectingSingleBroadcast(bcast);
494 LinkEvent event6 = linkStore.createOrUpdateLink(PIDA,
495 new DefaultLinkDescription(src, dst, DIRECT, A1_2));
496 verifyLinkBroadcastMessage(PIDA, NID1, src, dst, DIRECT, bcast);
497
498 assertLink(DID1, P1, DID2, P2, DIRECT, event6.subject());
499 assertAnnotationsEquals(event6.subject().annotations(), A2, A2_2, A1, A1_2);
500 assertEquals(LINK_UPDATED, event6.type());
501
502 // update link type (Ancillary) : ignored
503 resetCommunicatorExpectingNoBroadcast(bcast);
504 LinkEvent event7 = linkStore.createOrUpdateLink(PIDA,
505 new DefaultLinkDescription(src, dst, EDGE));
506 verifyNoBroadcastMessage(bcast);
507 assertNull("Ancillary change other than annotation is ignored", event7);
508 }
509
510
511 @Test
512 public final void testRemoveLink() {
513 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
514 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
515 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
516 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
517
518 putLink(linkId1, DIRECT, A1);
519 putLink(linkId2, DIRECT, A2);
520
521 // DID1,P1 => DID2,P2
522 // DID2,P2 => DID1,P1
523 // DID1,P2 => DID2,P3
524
525 LinkEvent event = linkStore.removeLink(d1P1, d2P2);
526 assertEquals(LINK_REMOVED, event.type());
527 assertAnnotationsEquals(event.subject().annotations(), A1);
528 LinkEvent event2 = linkStore.removeLink(d1P1, d2P2);
529 assertNull(event2);
530
531 assertLink(linkId2, DIRECT, linkStore.getLink(d2P2, d1P1));
532 assertAnnotationsEquals(linkStore.getLink(d2P2, d1P1).annotations(), A2);
533
534 // annotations, etc. should not survive remove
535 putLink(linkId1, DIRECT);
536 assertLink(linkId1, DIRECT, linkStore.getLink(d1P1, d2P2));
537 assertAnnotationsEquals(linkStore.getLink(d1P1, d2P2).annotations());
538 }
539
540 @Test
541 public final void testAncillaryVisible() {
542 ConnectPoint src = new ConnectPoint(DID1, P1);
543 ConnectPoint dst = new ConnectPoint(DID2, P2);
544
545 // add Ancillary link
546 linkStore.createOrUpdateLink(PIDA,
547 new DefaultLinkDescription(src, dst, INDIRECT, A1));
548
549 // Ancillary only link should not be visible
550 assertEquals(1, linkStore.getLinkCount());
551 assertNotNull(linkStore.getLink(src, dst));
552 }
553
554 // If Delegates should be called only on remote events,
555 // then Simple* should never call them, thus not test required.
556 @Ignore("Ignore until Delegate spec. is clear.")
557 @Test
558 public final void testEvents() throws InterruptedException {
559
560 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
561 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
562 final LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
563
564 final CountDownLatch addLatch = new CountDownLatch(1);
565 LinkStoreDelegate checkAdd = new LinkStoreDelegate() {
566 @Override
567 public void notify(LinkEvent event) {
568 assertEquals(LINK_ADDED, event.type());
569 assertLink(linkId1, INDIRECT, event.subject());
570 addLatch.countDown();
571 }
572 };
573 final CountDownLatch updateLatch = new CountDownLatch(1);
574 LinkStoreDelegate checkUpdate = new LinkStoreDelegate() {
575 @Override
576 public void notify(LinkEvent event) {
577 assertEquals(LINK_UPDATED, event.type());
578 assertLink(linkId1, DIRECT, event.subject());
579 updateLatch.countDown();
580 }
581 };
582 final CountDownLatch removeLatch = new CountDownLatch(1);
583 LinkStoreDelegate checkRemove = new LinkStoreDelegate() {
584 @Override
585 public void notify(LinkEvent event) {
586 assertEquals(LINK_REMOVED, event.type());
587 assertLink(linkId1, DIRECT, event.subject());
588 removeLatch.countDown();
589 }
590 };
591
592 linkStore.setDelegate(checkAdd);
593 putLink(linkId1, INDIRECT);
594 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
595
596 linkStore.unsetDelegate(checkAdd);
597 linkStore.setDelegate(checkUpdate);
598 putLink(linkId1, DIRECT);
599 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
600
601 linkStore.unsetDelegate(checkUpdate);
602 linkStore.setDelegate(checkRemove);
603 linkStore.removeLink(d1P1, d2P2);
604 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
605 }
606
607 private static final class TestClusterService extends StaticClusterService {
608
609 public TestClusterService() {
610 localNode = ONOS1;
611 nodes.put(NID1, ONOS1);
612 nodeStates.put(NID1, ACTIVE);
613
614 nodes.put(NID2, ONOS2);
615 nodeStates.put(NID2, ACTIVE);
616 }
617 }
618}