blob: bf7af464f0647c03d3a3345fbc6a5f248c70b458 [file] [log] [blame]
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -08001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -08003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.store.link.impl;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080017
18import com.google.common.collect.Iterables;
Madan Jampani2af244a2015-02-22 13:12:01 -080019
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080020import 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;
Jonathan Hart7d656f42015-01-27 14:07:23 -080027import org.onlab.packet.IpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.cluster.ControllerNode;
29import org.onosproject.cluster.DefaultControllerNode;
30import org.onosproject.cluster.NodeId;
Marc De Leenheerb473b9d2015-02-06 15:21:03 -080031import org.onosproject.mastership.MastershipServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.ConnectPoint;
33import org.onosproject.net.DefaultAnnotations;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.Link;
36import org.onosproject.net.Link.Type;
37import org.onosproject.net.LinkKey;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.SparseAnnotations;
40import org.onosproject.net.device.DeviceClockService;
Madan Jampani565a66a2015-07-25 17:01:13 -070041import org.onosproject.net.device.DeviceClockServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.link.DefaultLinkDescription;
43import org.onosproject.net.link.LinkDescription;
44import org.onosproject.net.link.LinkEvent;
45import org.onosproject.net.link.LinkStore;
46import org.onosproject.net.link.LinkStoreDelegate;
47import org.onosproject.net.provider.ProviderId;
Madan Jampani565a66a2015-07-25 17:01:13 -070048import org.onosproject.store.Timestamp;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.store.cluster.StaticClusterService;
50import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
52import org.onosproject.store.cluster.messaging.MessageSubject;
Madan Jampani565a66a2015-07-25 17:01:13 -070053import org.onosproject.store.impl.MastershipBasedTimestamp;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080054
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080055import java.util.HashMap;
56import java.util.Map;
57import java.util.Set;
58import java.util.concurrent.CountDownLatch;
Madan Jampani2af244a2015-02-22 13:12:01 -080059import java.util.concurrent.ExecutorService;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080060import java.util.concurrent.TimeUnit;
Madan Jampani565a66a2015-07-25 17:01:13 -070061import java.util.concurrent.atomic.AtomicLong;
Madan Jampani2bfa94c2015-04-11 05:03:49 -070062import java.util.function.Function;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080063
Jonathan Hart7d656f42015-01-27 14:07:23 -080064import static org.easymock.EasyMock.*;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080065import static org.junit.Assert.*;
Brian O'Connorabafb502014-12-02 22:26:20 -080066import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
67import static org.onosproject.net.DeviceId.deviceId;
Jonathan Hart7d656f42015-01-27 14:07:23 -080068import static org.onosproject.net.Link.Type.DIRECT;
69import static org.onosproject.net.Link.Type.EDGE;
70import static org.onosproject.net.Link.Type.INDIRECT;
Brian O'Connorabafb502014-12-02 22:26:20 -080071import static org.onosproject.net.NetTestTools.assertAnnotationsEquals;
Jonathan Hart7d656f42015-01-27 14:07:23 -080072import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
73import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
74import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -080075
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
Madan Jampani565a66a2015-07-25 17:01:13 -0700120 private final AtomicLong ticker = new AtomicLong();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800121 private DeviceClockService deviceClockService;
122 private ClusterCommunicationService clusterCommunicator;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800123
124 @BeforeClass
125 public static void setUpBeforeClass() throws Exception {
126 }
127
128 @AfterClass
129 public static void tearDownAfterClass() throws Exception {
130 }
131
132 @Before
133 public void setUp() throws Exception {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800134 // TODO mock clusterCommunicator
135 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
136 clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
Madan Jampani2af244a2015-02-22 13:12:01 -0800137 anyObject(ClusterMessageHandler.class),
138 anyObject(ExecutorService.class));
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800139 expectLastCall().anyTimes();
140 replay(clusterCommunicator);
141
142 linkStoreImpl = new GossipLinkStore();
143 linkStoreImpl.deviceClockService = deviceClockService;
144 linkStoreImpl.clusterCommunicator = clusterCommunicator;
145 linkStoreImpl.clusterService = new TestClusterService();
Madan Jampani565a66a2015-07-25 17:01:13 -0700146 linkStoreImpl.deviceClockService = new TestDeviceClockService();
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800147 linkStoreImpl.mastershipService = new TestMastershipService();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800148 linkStoreImpl.activate();
149 linkStore = linkStoreImpl;
150
151 verify(clusterCommunicator);
152 reset(clusterCommunicator);
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800153
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800154 }
155
156 @After
157 public void tearDown() throws Exception {
158 linkStoreImpl.deactivate();
159 }
160
161 private void putLink(DeviceId srcId, PortNumber srcNum,
162 DeviceId dstId, PortNumber dstNum, Type type,
163 SparseAnnotations... annotations) {
164 ConnectPoint src = new ConnectPoint(srcId, srcNum);
165 ConnectPoint dst = new ConnectPoint(dstId, dstNum);
166 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700167 clusterCommunicator.<InternalLinkEvent>broadcast(
168 anyObject(InternalLinkEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
169 expectLastCall().anyTimes();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800170 replay(clusterCommunicator);
171 linkStore.createOrUpdateLink(PID, new DefaultLinkDescription(src, dst, type, annotations));
172 verify(clusterCommunicator);
173 }
174
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700175 private <T> void resetCommunicatorExpectingSingleBroadcast(
176 Capture<T> message,
177 Capture<MessageSubject> subject,
178 Capture<Function<T, byte[]>> encoder) {
179 message.reset();
180 subject.reset();
181 encoder.reset();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800182 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700183 clusterCommunicator.broadcast(capture(message), capture(subject), capture(encoder));
184 expectLastCall().once();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800185 replay(clusterCommunicator);
186 }
187
188 private void putLink(LinkKey key, Type type, SparseAnnotations... annotations) {
189 putLink(key.src().deviceId(), key.src().port(),
190 key.dst().deviceId(), key.dst().port(),
191 type, annotations);
192 }
193
194 private static void assertLink(DeviceId srcId, PortNumber srcNum,
195 DeviceId dstId, PortNumber dstNum, Type type,
196 Link link) {
197 assertEquals(srcId, link.src().deviceId());
198 assertEquals(srcNum, link.src().port());
199 assertEquals(dstId, link.dst().deviceId());
200 assertEquals(dstNum, link.dst().port());
201 assertEquals(type, link.type());
202 }
203
204 private static void assertLink(LinkKey key, Type type, Link link) {
205 assertLink(key.src().deviceId(), key.src().port(),
206 key.dst().deviceId(), key.dst().port(),
207 type, link);
208 }
209
210 @Test
211 public final void testGetLinkCount() {
212 assertEquals("initialy empty", 0, linkStore.getLinkCount());
213
214 putLink(DID1, P1, DID2, P2, DIRECT);
215 putLink(DID2, P2, DID1, P1, DIRECT);
216 putLink(DID1, P1, DID2, P2, DIRECT);
217
218 assertEquals("expecting 2 unique link", 2, linkStore.getLinkCount());
219 }
220
221 @Test
222 public final void testGetLinks() {
223 assertEquals("initialy empty", 0,
224 Iterables.size(linkStore.getLinks()));
225
226 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
227 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
228
229 putLink(linkId1, DIRECT);
230 putLink(linkId2, DIRECT);
231 putLink(linkId1, DIRECT);
232
233 assertEquals("expecting 2 unique link", 2,
234 Iterables.size(linkStore.getLinks()));
235
236 Map<LinkKey, Link> links = new HashMap<>();
237 for (Link link : linkStore.getLinks()) {
238 links.put(LinkKey.linkKey(link), link);
239 }
240
241 assertLink(linkId1, DIRECT, links.get(linkId1));
242 assertLink(linkId2, DIRECT, links.get(linkId2));
243 }
244
245 @Test
246 public final void testGetDeviceEgressLinks() {
247 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
248 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
249 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
250
251 putLink(linkId1, DIRECT);
252 putLink(linkId2, DIRECT);
253 putLink(linkId3, DIRECT);
254
255 // DID1,P1 => DID2,P2
256 // DID2,P2 => DID1,P1
257 // DID1,P2 => DID2,P3
258
259 Set<Link> links1 = linkStore.getDeviceEgressLinks(DID1);
260 assertEquals(2, links1.size());
261 // check
262
263 Set<Link> links2 = linkStore.getDeviceEgressLinks(DID2);
264 assertEquals(1, links2.size());
265 assertLink(linkId2, DIRECT, links2.iterator().next());
266 }
267
268 @Test
269 public final void testGetDeviceIngressLinks() {
270 LinkKey linkId1 = LinkKey.linkKey(new ConnectPoint(DID1, P1), new ConnectPoint(DID2, P2));
271 LinkKey linkId2 = LinkKey.linkKey(new ConnectPoint(DID2, P2), new ConnectPoint(DID1, P1));
272 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
273
274 putLink(linkId1, DIRECT);
275 putLink(linkId2, DIRECT);
276 putLink(linkId3, DIRECT);
277
278 // DID1,P1 => DID2,P2
279 // DID2,P2 => DID1,P1
280 // DID1,P2 => DID2,P3
281
282 Set<Link> links1 = linkStore.getDeviceIngressLinks(DID2);
283 assertEquals(2, links1.size());
284 // check
285
286 Set<Link> links2 = linkStore.getDeviceIngressLinks(DID1);
287 assertEquals(1, links2.size());
288 assertLink(linkId2, DIRECT, links2.iterator().next());
289 }
290
291 @Test
292 public final void testGetLink() {
293 ConnectPoint src = new ConnectPoint(DID1, P1);
294 ConnectPoint dst = new ConnectPoint(DID2, P2);
295 LinkKey linkId1 = LinkKey.linkKey(src, dst);
296
297 putLink(linkId1, DIRECT);
298
299 Link link = linkStore.getLink(src, dst);
300 assertLink(linkId1, DIRECT, link);
301
302 assertNull("There shouldn't be reverese link",
303 linkStore.getLink(dst, src));
304 }
305
306 @Test
307 public final void testGetEgressLinks() {
308 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
309 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
310 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
311 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
312 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
313
314 putLink(linkId1, DIRECT);
315 putLink(linkId2, DIRECT);
316 putLink(linkId3, DIRECT);
317
318 // DID1,P1 => DID2,P2
319 // DID2,P2 => DID1,P1
320 // DID1,P2 => DID2,P3
321
322 Set<Link> links1 = linkStore.getEgressLinks(d1P1);
323 assertEquals(1, links1.size());
324 assertLink(linkId1, DIRECT, links1.iterator().next());
325
326 Set<Link> links2 = linkStore.getEgressLinks(d2P2);
327 assertEquals(1, links2.size());
328 assertLink(linkId2, DIRECT, links2.iterator().next());
329 }
330
331 @Test
332 public final void testGetIngressLinks() {
333 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
334 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
335 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
336 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
337 LinkKey linkId3 = LinkKey.linkKey(new ConnectPoint(DID1, P2), new ConnectPoint(DID2, P3));
338
339 putLink(linkId1, DIRECT);
340 putLink(linkId2, DIRECT);
341 putLink(linkId3, DIRECT);
342
343 // DID1,P1 => DID2,P2
344 // DID2,P2 => DID1,P1
345 // DID1,P2 => DID2,P3
346
347 Set<Link> links1 = linkStore.getIngressLinks(d2P2);
348 assertEquals(1, links1.size());
349 assertLink(linkId1, DIRECT, links1.iterator().next());
350
351 Set<Link> links2 = linkStore.getIngressLinks(d1P1);
352 assertEquals(1, links2.size());
353 assertLink(linkId2, DIRECT, links2.iterator().next());
354 }
355
356 @Test
357 public final void testCreateOrUpdateLink() {
358 ConnectPoint src = new ConnectPoint(DID1, P1);
359 ConnectPoint dst = new ConnectPoint(DID2, P2);
360
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700361 Capture<InternalLinkEvent> message = new Capture<>();
362 Capture<MessageSubject> subject = new Capture<>();
363 Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800364
365 // add link
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700366 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800367 final DefaultLinkDescription linkDescription = new DefaultLinkDescription(src, dst, INDIRECT);
368 LinkEvent event = linkStore.createOrUpdateLink(PID,
369 linkDescription);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700370 verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800371
372 assertLink(DID1, P1, DID2, P2, INDIRECT, event.subject());
373 assertEquals(LINK_ADDED, event.type());
374
375 // update link type
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700376 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800377 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
378 new DefaultLinkDescription(src, dst, DIRECT));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700379 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800380
381 assertLink(DID1, P1, DID2, P2, DIRECT, event2.subject());
382 assertEquals(LINK_UPDATED, event2.type());
383
384 // no change
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700385 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800386 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
387 new DefaultLinkDescription(src, dst, DIRECT));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700388 verifyNoBroadcastMessage(message);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800389
390 assertNull("No change event expected", event3);
391 }
392
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700393 private <T> void verifyNoBroadcastMessage(Capture<T> message) {
394 assertFalse("No broadcast expected", message.hasCaptured());
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800395 }
396
397 private void verifyLinkBroadcastMessage(ProviderId providerId,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700398 NodeId sender,
399 ConnectPoint src,
400 ConnectPoint dst,
401 Type type,
402 Capture<InternalLinkEvent> actualLinkEvent,
403 Capture<MessageSubject> actualSubject,
404 Capture<Function<InternalLinkEvent, byte[]>> actualEncoder) {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800405 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700406 assertTrue(actualLinkEvent.hasCaptured());
407 assertEquals(GossipLinkStoreMessageSubjects.LINK_UPDATE, actualSubject.getValue());
408 assertEquals(providerId, actualLinkEvent.getValue().providerId());
409 assertLinkDescriptionEquals(src, dst, type, actualLinkEvent.getValue().linkDescription().value());
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800410 }
411
412 private static void assertLinkDescriptionEquals(ConnectPoint src,
413 ConnectPoint dst,
414 Type type,
415 LinkDescription actual) {
416 assertEquals(src, actual.src());
417 assertEquals(dst, actual.dst());
418 assertEquals(type, actual.type());
419 // TODO check annotations
420 }
421
422 @Test
423 public final void testCreateOrUpdateLinkAncillary() {
424 ConnectPoint src = new ConnectPoint(DID1, P1);
425 ConnectPoint dst = new ConnectPoint(DID2, P2);
426
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700427 Capture<InternalLinkEvent> message = new Capture<>();
428 Capture<MessageSubject> subject = new Capture<>();
429 Capture<Function<InternalLinkEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800430
431 // add Ancillary link
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700432 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800433 LinkEvent event = linkStore.createOrUpdateLink(PIDA,
434 new DefaultLinkDescription(src, dst, INDIRECT, A1));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700435 verifyLinkBroadcastMessage(PIDA, NID1, src, dst, INDIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800436
437 assertNotNull("Ancillary only link is ignored", event);
438
439 // add Primary link
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700440 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800441 LinkEvent event2 = linkStore.createOrUpdateLink(PID,
442 new DefaultLinkDescription(src, dst, INDIRECT, A2));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700443 verifyLinkBroadcastMessage(PID, NID1, src, dst, INDIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800444
445 assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject());
446 assertAnnotationsEquals(event2.subject().annotations(), A2, A1);
447 assertEquals(LINK_UPDATED, event2.type());
448
449 // update link type
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700450 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800451 LinkEvent event3 = linkStore.createOrUpdateLink(PID,
452 new DefaultLinkDescription(src, dst, DIRECT, A2));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700453 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800454
455 assertLink(DID1, P1, DID2, P2, DIRECT, event3.subject());
456 assertAnnotationsEquals(event3.subject().annotations(), A2, A1);
457 assertEquals(LINK_UPDATED, event3.type());
458
459
460 // no change
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700461 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800462 LinkEvent event4 = linkStore.createOrUpdateLink(PID,
463 new DefaultLinkDescription(src, dst, DIRECT));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700464 verifyNoBroadcastMessage(message);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800465
466 assertNull("No change event expected", event4);
467
468 // update link annotation (Primary)
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700469 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800470 LinkEvent event5 = linkStore.createOrUpdateLink(PID,
471 new DefaultLinkDescription(src, dst, DIRECT, A2_2));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700472 verifyLinkBroadcastMessage(PID, NID1, src, dst, DIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800473
474 assertLink(DID1, P1, DID2, P2, DIRECT, event5.subject());
475 assertAnnotationsEquals(event5.subject().annotations(), A2, A2_2, A1);
476 assertEquals(LINK_UPDATED, event5.type());
477
478 // update link annotation (Ancillary)
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700479 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800480 LinkEvent event6 = linkStore.createOrUpdateLink(PIDA,
481 new DefaultLinkDescription(src, dst, DIRECT, A1_2));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700482 verifyLinkBroadcastMessage(PIDA, NID1, src, dst, DIRECT, message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800483
484 assertLink(DID1, P1, DID2, P2, DIRECT, event6.subject());
485 assertAnnotationsEquals(event6.subject().annotations(), A2, A2_2, A1, A1_2);
486 assertEquals(LINK_UPDATED, event6.type());
487
488 // update link type (Ancillary) : ignored
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700489 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800490 LinkEvent event7 = linkStore.createOrUpdateLink(PIDA,
491 new DefaultLinkDescription(src, dst, EDGE));
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700492 verifyNoBroadcastMessage(message);
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800493 assertNull("Ancillary change other than annotation is ignored", event7);
494 }
495
496
497 @Test
498 public final void testRemoveLink() {
499 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
500 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
501 LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
502 LinkKey linkId2 = LinkKey.linkKey(d2P2, d1P1);
503
504 putLink(linkId1, DIRECT, A1);
505 putLink(linkId2, DIRECT, A2);
506
507 // DID1,P1 => DID2,P2
508 // DID2,P2 => DID1,P1
509 // DID1,P2 => DID2,P3
510
511 LinkEvent event = linkStore.removeLink(d1P1, d2P2);
512 assertEquals(LINK_REMOVED, event.type());
513 assertAnnotationsEquals(event.subject().annotations(), A1);
514 LinkEvent event2 = linkStore.removeLink(d1P1, d2P2);
515 assertNull(event2);
516
517 assertLink(linkId2, DIRECT, linkStore.getLink(d2P2, d1P1));
518 assertAnnotationsEquals(linkStore.getLink(d2P2, d1P1).annotations(), A2);
519
520 // annotations, etc. should not survive remove
521 putLink(linkId1, DIRECT);
522 assertLink(linkId1, DIRECT, linkStore.getLink(d1P1, d2P2));
523 assertAnnotationsEquals(linkStore.getLink(d1P1, d2P2).annotations());
524 }
525
526 @Test
527 public final void testAncillaryVisible() {
528 ConnectPoint src = new ConnectPoint(DID1, P1);
529 ConnectPoint dst = new ConnectPoint(DID2, P2);
530
531 // add Ancillary link
532 linkStore.createOrUpdateLink(PIDA,
533 new DefaultLinkDescription(src, dst, INDIRECT, A1));
534
535 // Ancillary only link should not be visible
536 assertEquals(1, linkStore.getLinkCount());
537 assertNotNull(linkStore.getLink(src, dst));
538 }
539
540 // If Delegates should be called only on remote events,
541 // then Simple* should never call them, thus not test required.
542 @Ignore("Ignore until Delegate spec. is clear.")
543 @Test
544 public final void testEvents() throws InterruptedException {
545
546 final ConnectPoint d1P1 = new ConnectPoint(DID1, P1);
547 final ConnectPoint d2P2 = new ConnectPoint(DID2, P2);
548 final LinkKey linkId1 = LinkKey.linkKey(d1P1, d2P2);
549
550 final CountDownLatch addLatch = new CountDownLatch(1);
551 LinkStoreDelegate checkAdd = new LinkStoreDelegate() {
552 @Override
553 public void notify(LinkEvent event) {
554 assertEquals(LINK_ADDED, event.type());
555 assertLink(linkId1, INDIRECT, event.subject());
556 addLatch.countDown();
557 }
558 };
559 final CountDownLatch updateLatch = new CountDownLatch(1);
560 LinkStoreDelegate checkUpdate = new LinkStoreDelegate() {
561 @Override
562 public void notify(LinkEvent event) {
563 assertEquals(LINK_UPDATED, event.type());
564 assertLink(linkId1, DIRECT, event.subject());
565 updateLatch.countDown();
566 }
567 };
568 final CountDownLatch removeLatch = new CountDownLatch(1);
569 LinkStoreDelegate checkRemove = new LinkStoreDelegate() {
570 @Override
571 public void notify(LinkEvent event) {
572 assertEquals(LINK_REMOVED, event.type());
573 assertLink(linkId1, DIRECT, event.subject());
574 removeLatch.countDown();
575 }
576 };
577
578 linkStore.setDelegate(checkAdd);
579 putLink(linkId1, INDIRECT);
580 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
581
582 linkStore.unsetDelegate(checkAdd);
583 linkStore.setDelegate(checkUpdate);
584 putLink(linkId1, DIRECT);
585 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
586
587 linkStore.unsetDelegate(checkUpdate);
588 linkStore.setDelegate(checkRemove);
589 linkStore.removeLink(d1P1, d2P2);
590 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
591 }
592
593 private static final class TestClusterService extends StaticClusterService {
594
595 public TestClusterService() {
596 localNode = ONOS1;
597 nodes.put(NID1, ONOS1);
598 nodeStates.put(NID1, ACTIVE);
599
600 nodes.put(NID2, ONOS2);
601 nodeStates.put(NID2, ACTIVE);
602 }
603 }
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800604
Madan Jampani565a66a2015-07-25 17:01:13 -0700605 private final class TestDeviceClockService extends DeviceClockServiceAdapter {
606
607 private final AtomicLong ticker = new AtomicLong();
608
609 @Override
610 public Timestamp getTimestamp(DeviceId deviceId) {
611 if (DID1.equals(deviceId)) {
612 return new MastershipBasedTimestamp(1, ticker.getAndIncrement());
613 } else if (DID2.equals(deviceId)) {
614 return new MastershipBasedTimestamp(2, ticker.getAndIncrement());
615 } else {
616 throw new IllegalStateException();
617 }
618 }
619
620 @Override
621 public boolean isTimestampAvailable(DeviceId deviceId) {
622 return DID1.equals(deviceId) || DID2.equals(deviceId);
623 }
624 }
625
Marc De Leenheerb473b9d2015-02-06 15:21:03 -0800626 private final class TestMastershipService extends MastershipServiceAdapter {
627 @Override
628 public NodeId getMasterFor(DeviceId deviceId) {
629 return NID1;
630 }
631 }
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800632}