blob: 9c9ef2c7999a5ad4e6df287a4c1d9a6453b8f6eb [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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.device.impl;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070017
Jonathan Hart7d656f42015-01-27 14:07:23 -080018import com.google.common.collect.Iterables;
19import com.google.common.collect.Sets;
Madan Jampani2af244a2015-02-22 13:12:01 -080020
Yuta HIGUCHI47c40882014-10-10 18:44:37 -070021import org.easymock.Capture;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070022import org.junit.After;
23import org.junit.AfterClass;
24import org.junit.Before;
25import org.junit.BeforeClass;
26import org.junit.Ignore;
27import org.junit.Test;
Jonathan Hart7d656f42015-01-27 14:07:23 -080028import org.onlab.packet.ChassisId;
29import org.onlab.packet.IpAddress;
Madan Jampanif4c88502016-01-21 12:35:36 -080030import org.onlab.util.KryoNamespace;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.cluster.ClusterService;
32import org.onosproject.cluster.ControllerNode;
33import org.onosproject.cluster.DefaultControllerNode;
34import org.onosproject.cluster.NodeId;
35import org.onosproject.mastership.MastershipServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.Annotations;
37import org.onosproject.net.DefaultAnnotations;
38import org.onosproject.net.Device;
39import org.onosproject.net.DeviceId;
Madan Jampanic6e574f2015-05-29 13:41:52 -070040import org.onosproject.net.MastershipRole;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.Port;
42import org.onosproject.net.PortNumber;
43import org.onosproject.net.SparseAnnotations;
44import org.onosproject.net.device.DefaultDeviceDescription;
45import org.onosproject.net.device.DefaultPortDescription;
46import org.onosproject.net.device.DeviceClockService;
Madan Jampani565a66a2015-07-25 17:01:13 -070047import org.onosproject.net.device.DeviceClockServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.device.DeviceDescription;
49import org.onosproject.net.device.DeviceEvent;
50import org.onosproject.net.device.DeviceStore;
51import org.onosproject.net.device.DeviceStoreDelegate;
52import org.onosproject.net.device.PortDescription;
53import org.onosproject.net.provider.ProviderId;
Madan Jampani565a66a2015-07-25 17:01:13 -070054import org.onosproject.store.Timestamp;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.store.cluster.StaticClusterService;
56import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
57import org.onosproject.store.cluster.messaging.ClusterMessage;
58import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
59import org.onosproject.store.cluster.messaging.MessageSubject;
Madan Jampani565a66a2015-07-25 17:01:13 -070060import org.onosproject.store.impl.MastershipBasedTimestamp;
Madan Jampanif4c88502016-01-21 12:35:36 -080061import org.onosproject.store.service.EventuallyConsistentMap;
62import org.onosproject.store.service.EventuallyConsistentMapBuilder;
63import org.onosproject.store.service.StorageService;
Jonathan Hart7d656f42015-01-27 14:07:23 -080064import java.io.IOException;
65import java.util.Arrays;
66import java.util.Collections;
67import java.util.HashMap;
68import java.util.List;
69import java.util.Map;
70import java.util.Set;
Madan Jampanic6e574f2015-05-29 13:41:52 -070071import java.util.concurrent.CompletableFuture;
Jonathan Hart7d656f42015-01-27 14:07:23 -080072import java.util.concurrent.CountDownLatch;
Madan Jampani2af244a2015-02-22 13:12:01 -080073import java.util.concurrent.ExecutorService;
Jonathan Hart7d656f42015-01-27 14:07:23 -080074import java.util.concurrent.TimeUnit;
Madan Jampani565a66a2015-07-25 17:01:13 -070075import java.util.concurrent.atomic.AtomicLong;
Madan Jampanif4c88502016-01-21 12:35:36 -080076import java.util.function.BiFunction;
Madan Jampani2bfa94c2015-04-11 05:03:49 -070077import java.util.function.Function;
Jonathan Hart7d656f42015-01-27 14:07:23 -080078
79import static java.util.Arrays.asList;
80import static org.easymock.EasyMock.*;
81import static org.junit.Assert.*;
82import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
83import static org.onosproject.net.DefaultAnnotations.union;
84import static org.onosproject.net.Device.Type.SWITCH;
85import static org.onosproject.net.DeviceId.deviceId;
86import static org.onosproject.net.device.DeviceEvent.Type.*;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070087
88
89// TODO add tests for remote replication
90/**
91 * Test of the gossip based distributed DeviceStore implementation.
92 */
93public class GossipDeviceStoreTest {
94
95 private static final ProviderId PID = new ProviderId("of", "foo");
96 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
97 private static final DeviceId DID1 = deviceId("of:foo");
98 private static final DeviceId DID2 = deviceId("of:bar");
99 private static final String MFR = "whitebox";
100 private static final String HW = "1.1.x";
101 private static final String SW1 = "3.8.1";
102 private static final String SW2 = "3.9.5";
103 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -0700104 private static final ChassisId CID = new ChassisId();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700105
106 private static final PortNumber P1 = PortNumber.portNumber(1);
107 private static final PortNumber P2 = PortNumber.portNumber(2);
108 private static final PortNumber P3 = PortNumber.portNumber(3);
109
110 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
111 .set("A1", "a1")
112 .set("B1", "b1")
113 .build();
114 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
115 .remove("A1")
116 .set("B3", "b3")
117 .build();
118 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
119 .set("A2", "a2")
120 .set("B2", "b2")
121 .build();
122 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
123 .remove("A2")
124 .set("B4", "b4")
125 .build();
126
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700127 // local node
128 private static final NodeId NID1 = new NodeId("local");
129 private static final ControllerNode ONOS1 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700130 new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1"));
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700131
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700132 // remote node
133 private static final NodeId NID2 = new NodeId("remote");
134 private static final ControllerNode ONOS2 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700135 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700136 private static final List<SparseAnnotations> NO_ANNOTATION = Collections.emptyList();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700137
Madan Jampanif4c88502016-01-21 12:35:36 -0800138 EventuallyConsistentMapBuilder ecMapBuilder;
139 EventuallyConsistentMap ecMap;
140 StorageService testStorageService;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700141 private TestGossipDeviceStore testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700142 private GossipDeviceStore gossipDeviceStore;
143 private DeviceStore deviceStore;
144
Madan Jampani565a66a2015-07-25 17:01:13 -0700145 private DeviceClockService deviceClockService = new TestDeviceClockService();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700146 private ClusterCommunicationService clusterCommunicator;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800147
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700148 @BeforeClass
149 public static void setUpBeforeClass() throws Exception {
150 }
151
152 @AfterClass
153 public static void tearDownAfterClass() throws Exception {
154 }
155
156
157 @Before
158 public void setUp() throws Exception {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700159 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
160 clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700161 anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700162 expectLastCall().anyTimes();
163 replay(clusterCommunicator);
Madan Jampani53e44e62014-10-07 12:39:51 -0700164 ClusterService clusterService = new TestClusterService();
Madan Jampani47c93732014-10-06 20:46:08 -0700165
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700166 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700167 testGossipDeviceStore.mastershipService = new TestMastershipService();
168
Madan Jampanif4c88502016-01-21 12:35:36 -0800169 ecMapBuilder = createNiceMock(EventuallyConsistentMapBuilder.class);
170 expect(ecMapBuilder.withName(anyObject(String.class))).andReturn(ecMapBuilder).anyTimes();
171 expect(ecMapBuilder.withSerializer(anyObject(KryoNamespace.Builder.class))).andReturn(ecMapBuilder).anyTimes();
172 expect(ecMapBuilder.withAntiEntropyPeriod(5, TimeUnit.SECONDS)).andReturn(ecMapBuilder).anyTimes();
173 expect(ecMapBuilder.withTimestampProvider(anyObject(BiFunction.class))).andReturn(ecMapBuilder).anyTimes();
174 expect(ecMapBuilder.withTombstonesDisabled()).andReturn(ecMapBuilder).anyTimes();
175
176 ecMap = createNiceMock(EventuallyConsistentMap.class);
177 expect(ecMapBuilder.build()).andReturn(ecMap).anyTimes();
178 testStorageService = createNiceMock(StorageService.class);
179 expect(testStorageService.eventuallyConsistentMapBuilder()).andReturn(ecMapBuilder).anyTimes();
180
181 replay(testStorageService, ecMapBuilder, ecMap);
182
183 testGossipDeviceStore.storageService = testStorageService;
Madan Jampani565a66a2015-07-25 17:01:13 -0700184 testGossipDeviceStore.deviceClockService = deviceClockService;
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700185
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700186 gossipDeviceStore = testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700187 gossipDeviceStore.activate();
188 deviceStore = gossipDeviceStore;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700189 verify(clusterCommunicator);
190 reset(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700191 }
192
193 @After
194 public void tearDown() throws Exception {
195 gossipDeviceStore.deactivate();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700196 }
197
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700198 private void putDevice(DeviceId deviceId, String swVersion,
199 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700200 DeviceDescription description =
201 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700202 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700203 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700204 clusterCommunicator.<InternalDeviceEvent>broadcast(
205 anyObject(InternalDeviceEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
206 expectLastCall().anyTimes();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700207 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700208 deviceStore.createOrUpdateDevice(PID, deviceId, description);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700209 verify(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700210 }
211
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700212 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
213 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700214 DeviceDescription description =
215 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700216 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700217 deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
218 }
219
220 private static void assertDevice(DeviceId id, String swVersion, Device device) {
221 assertNotNull(device);
222 assertEquals(id, device.id());
223 assertEquals(MFR, device.manufacturer());
224 assertEquals(HW, device.hwVersion());
225 assertEquals(swVersion, device.swVersion());
226 assertEquals(SN, device.serialNumber());
227 }
228
229 /**
230 * Verifies that Annotations created by merging {@code annotations} is
231 * equal to actual Annotations.
232 *
233 * @param actual Annotations to check
234 * @param annotations
235 */
236 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700237 SparseAnnotations expected = DefaultAnnotations.builder().build();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700238 for (SparseAnnotations a : annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700239 expected = DefaultAnnotations.union(expected, a);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700240 }
241 assertEquals(expected.keys(), actual.keys());
242 for (String key : expected.keys()) {
243 assertEquals(expected.value(key), actual.value(key));
244 }
245 }
246
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700247 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
248 DeviceDescription actual) {
249 if (expected == actual) {
250 return;
251 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800252 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700253 assertEquals(expected.hwVersion(), actual.hwVersion());
254 assertEquals(expected.manufacturer(), actual.manufacturer());
255 assertEquals(expected.serialNumber(), actual.serialNumber());
256 assertEquals(expected.swVersion(), actual.swVersion());
257
258 assertAnnotationsEquals(actual.annotations(), expected.annotations());
259 }
260
261 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
262 List<SparseAnnotations> expectedAnnotations,
263 DeviceDescription actual) {
264 if (expected == actual) {
265 return;
266 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800267 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700268 assertEquals(expected.hwVersion(), actual.hwVersion());
269 assertEquals(expected.manufacturer(), actual.manufacturer());
270 assertEquals(expected.serialNumber(), actual.serialNumber());
271 assertEquals(expected.swVersion(), actual.swVersion());
272
273 assertAnnotationsEquals(actual.annotations(),
274 expectedAnnotations.toArray(new SparseAnnotations[0]));
275 }
276
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700277 @Test
278 public final void testGetDeviceCount() {
279 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
280
281 putDevice(DID1, SW1);
282 putDevice(DID2, SW2);
283 putDevice(DID1, SW1);
284
285 assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
286 }
287
288 @Test
289 public final void testGetDevices() {
290 assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
291
292 putDevice(DID1, SW1);
293 putDevice(DID2, SW2);
294 putDevice(DID1, SW1);
295
296 assertEquals("expect 2 uniq devices",
297 2, Iterables.size(deviceStore.getDevices()));
298
299 Map<DeviceId, Device> devices = new HashMap<>();
300 for (Device device : deviceStore.getDevices()) {
301 devices.put(device.id(), device);
302 }
303
304 assertDevice(DID1, SW1, devices.get(DID1));
305 assertDevice(DID2, SW2, devices.get(DID2));
306
307 // add case for new node?
308 }
309
310 @Test
311 public final void testGetDevice() {
312
313 putDevice(DID1, SW1);
314
315 assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
316 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
317 }
318
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700319 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700320 DeviceId deviceId,
321 ProviderId providerId,
322 DeviceDescription expectedDesc,
323 Capture<InternalDeviceEvent> actualEvent,
324 Capture<MessageSubject> actualSubject,
325 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
326 assertTrue(actualEvent.hasCaptured());
327 assertTrue(actualSubject.hasCaptured());
328 assertTrue(actualEncoder.hasCaptured());
329
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700330 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700331 actualSubject.getValue());
332 assertEquals(deviceId, actualEvent.getValue().deviceId());
333 assertEquals(providerId, actualEvent.getValue().providerId());
334 assertDeviceDescriptionEquals(expectedDesc, actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700335 }
336
337 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700338 DeviceId deviceId,
339 ProviderId providerId,
340 DeviceDescription expectedDesc,
341 List<SparseAnnotations> expectedAnnotations,
342 Capture<InternalDeviceEvent> actualEvent,
343 Capture<MessageSubject> actualSubject,
344 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
345 assertTrue(actualEvent.hasCaptured());
346 assertTrue(actualSubject.hasCaptured());
347 assertTrue(actualEncoder.hasCaptured());
348
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700349 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700350 actualSubject.getValue());
351 assertEquals(deviceId, actualEvent.getValue().deviceId());
352 assertEquals(providerId, actualEvent.getValue().providerId());
353 assertDeviceDescriptionEquals(
354 expectedDesc,
355 expectedAnnotations,
356 actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700357 }
358
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700359 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700360 public final void testCreateOrUpdateDevice() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700361 DeviceDescription description =
362 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700363 HW, SW1, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700364 Capture<InternalDeviceEvent> message = new Capture<>();
365 Capture<MessageSubject> subject = new Capture<>();
366 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700367
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700368 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700369 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
370 assertEquals(DEVICE_ADDED, event.type());
371 assertDevice(DID1, SW1, event.subject());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700372 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700373 assertInternalDeviceEvent(NID1, DID1, PID, description, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700374
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700375
376 DeviceDescription description2 =
377 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700378 HW, SW2, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700379 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700380 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
381 assertEquals(DEVICE_UPDATED, event2.type());
382 assertDevice(DID1, SW2, event2.subject());
383
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700384 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700385 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700386 reset(clusterCommunicator);
387
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700388 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
389 }
390
391 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700392 public final void testCreateOrUpdateDeviceAncillary() throws IOException {
393 // add
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700394 DeviceDescription description =
395 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700396 HW, SW1, SN, CID, A2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700397 Capture<ClusterMessage> bcast = new Capture<>();
398
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700399 Capture<InternalDeviceEvent> message = new Capture<>();
400 Capture<MessageSubject> subject = new Capture<>();
401 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
402
403 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700404 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
405 assertEquals(DEVICE_ADDED, event.type());
406 assertDevice(DID1, SW1, event.subject());
407 assertEquals(PIDA, event.subject().providerId());
408 assertAnnotationsEquals(event.subject().annotations(), A2);
409 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700410 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700411 assertInternalDeviceEvent(NID1, DID1, PIDA, description, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700412
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700413 // update from primary
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700414 DeviceDescription description2 =
415 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700416 HW, SW2, SN, CID, A1);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700417 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700418
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700419 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
420 assertEquals(DEVICE_UPDATED, event2.type());
421 assertDevice(DID1, SW2, event2.subject());
422 assertEquals(PID, event2.subject().providerId());
423 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
424 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700425 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700426 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700427
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700428 // no-op update from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700429 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700430 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
431
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700432 verify(clusterCommunicator);
433 assertFalse("no broadcast expected", bcast.hasCaptured());
434
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700435 // For now, Ancillary is ignored once primary appears
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700436 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700437
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700438 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
439
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700440 verify(clusterCommunicator);
441 assertFalse("no broadcast expected", bcast.hasCaptured());
442
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700443 // But, Ancillary annotations will be in effect
444 DeviceDescription description3 =
445 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700446 HW, SW1, SN, CID, A2_2);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700447 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700448
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700449 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
450 assertEquals(DEVICE_UPDATED, event3.type());
451 // basic information will be the one from Primary
452 assertDevice(DID1, SW2, event3.subject());
453 assertEquals(PID, event3.subject().providerId());
454 // but annotation from Ancillary will be merged
455 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
456 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700457 verify(clusterCommunicator);
458 // note: only annotation from PIDA is sent over the wire
459 assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700460 asList(union(A2, A2_2)), message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700461
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700462 }
463
464
465 @Test
466 public final void testMarkOffline() {
467
468 putDevice(DID1, SW1);
469 assertTrue(deviceStore.isAvailable(DID1));
470
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700471 Capture<InternalDeviceEvent> message = new Capture<>();
472 Capture<MessageSubject> subject = new Capture<>();
473 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700474
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700475 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700476 DeviceEvent event = deviceStore.markOffline(DID1);
477 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
478 assertDevice(DID1, SW1, event.subject());
479 assertFalse(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700480 verify(clusterCommunicator);
481 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700482 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700483
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700484
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700485 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700486 DeviceEvent event2 = deviceStore.markOffline(DID1);
487 assertNull("No change, no event", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700488 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700489 assertFalse(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700490 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700491
492 @Test
493 public final void testUpdatePorts() {
494 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700495 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700496 new DefaultPortDescription(P1, true),
497 new DefaultPortDescription(P2, true)
498 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700499 Capture<InternalDeviceEvent> message = new Capture<>();
500 Capture<MessageSubject> subject = new Capture<>();
501 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700502
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700503 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700504 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700505 verify(clusterCommunicator);
506 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700507 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700508
509 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
510 for (DeviceEvent event : events) {
511 assertEquals(PORT_ADDED, event.type());
512 assertDevice(DID1, SW1, event.subject());
513 assertTrue("PortNumber is one of expected",
514 expectedPorts.remove(event.port().number()));
515 assertTrue("Port is enabled", event.port().isEnabled());
516 }
517 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
518
519
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700520 List<PortDescription> pds2 = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700521 new DefaultPortDescription(P1, false),
522 new DefaultPortDescription(P2, true),
523 new DefaultPortDescription(P3, true)
524 );
525
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700526 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700527 events = deviceStore.updatePorts(PID, DID1, pds2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700528 verify(clusterCommunicator);
529 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700530 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700531
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700532 assertFalse("event should be triggered", events.isEmpty());
533 for (DeviceEvent event : events) {
534 PortNumber num = event.port().number();
535 if (P1.equals(num)) {
536 assertEquals(PORT_UPDATED, event.type());
537 assertDevice(DID1, SW1, event.subject());
538 assertFalse("Port is disabled", event.port().isEnabled());
539 } else if (P2.equals(num)) {
540 fail("P2 event not expected.");
541 } else if (P3.equals(num)) {
542 assertEquals(PORT_ADDED, event.type());
543 assertDevice(DID1, SW1, event.subject());
544 assertTrue("Port is enabled", event.port().isEnabled());
545 } else {
546 fail("Unknown port number encountered: " + num);
547 }
548 }
549
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700550 List<PortDescription> pds3 = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700551 new DefaultPortDescription(P1, false),
552 new DefaultPortDescription(P2, true)
553 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700554 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700555 events = deviceStore.updatePorts(PID, DID1, pds3);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700556 verify(clusterCommunicator);
557 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700558 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700559
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700560 assertFalse("event should be triggered", events.isEmpty());
561 for (DeviceEvent event : events) {
562 PortNumber num = event.port().number();
563 if (P1.equals(num)) {
564 fail("P1 event not expected.");
565 } else if (P2.equals(num)) {
566 fail("P2 event not expected.");
567 } else if (P3.equals(num)) {
568 assertEquals(PORT_REMOVED, event.type());
569 assertDevice(DID1, SW1, event.subject());
570 assertTrue("Port was enabled", event.port().isEnabled());
571 } else {
572 fail("Unknown port number encountered: " + num);
573 }
574 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700575 }
576
577 @Test
578 public final void testUpdatePortStatus() {
579 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700580 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700581 new DefaultPortDescription(P1, true)
582 );
583 deviceStore.updatePorts(PID, DID1, pds);
584
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700585 Capture<InternalPortStatusEvent> message = new Capture<>();
586 Capture<MessageSubject> subject = new Capture<>();
587 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700588
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700589 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700590 final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
591 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700592 assertEquals(PORT_UPDATED, event.type());
593 assertDevice(DID1, SW1, event.subject());
594 assertEquals(P1, event.port().number());
595 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700596 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700597 assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, message, subject, encoder);
598 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700599 }
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700600
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700601 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700602 public final void testUpdatePortStatusAncillary() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700603 putDeviceAncillary(DID1, SW1);
604 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700605 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700606 new DefaultPortDescription(P1, true, A1)
607 );
608 deviceStore.updatePorts(PID, DID1, pds);
609
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700610 Capture<InternalPortStatusEvent> message = new Capture<>();
611 Capture<MessageSubject> subject = new Capture<>();
612 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700613
614 // update port from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700615 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
616
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700617 final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
618 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700619 assertEquals(PORT_UPDATED, event.type());
620 assertDevice(DID1, SW1, event.subject());
621 assertEquals(P1, event.port().number());
622 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
623 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700624 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700625 assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), message, subject, encoder);
626 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700627
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700628 // update port from ancillary with no attributes
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700629 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700630 final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
631 DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700632 assertNull("Ancillary is ignored if primary exists", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700633 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700634 assertFalse(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700635
636 // but, Ancillary annotation update will be notified
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700637 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700638 final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
639 DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700640 assertEquals(PORT_UPDATED, event3.type());
641 assertDevice(DID1, SW1, event3.subject());
642 assertEquals(P1, event3.port().number());
643 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
644 assertFalse("Port is disabled", event3.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700645 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700646 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), message, subject, encoder);
647 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700648
649 // port only reported from Ancillary will be notified as down
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700650 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700651 final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
652 DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700653 assertEquals(PORT_ADDED, event4.type());
654 assertDevice(DID1, SW1, event4.subject());
655 assertEquals(P2, event4.port().number());
656 assertAnnotationsEquals(event4.port().annotations());
657 assertFalse("Port is disabled if not given from primary provider",
658 event4.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700659 verify(clusterCommunicator);
660 // TODO: verify broadcast message content
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700661 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, message, subject, encoder);
662 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700663 }
664
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700665 private void assertInternalPortStatusEvent(NodeId sender,
666 DeviceId did,
667 ProviderId pid,
668 DefaultPortDescription expectedDesc,
669 List<SparseAnnotations> expectedAnnotations,
670 Capture<InternalPortStatusEvent> actualEvent,
671 Capture<MessageSubject> actualSubject,
672 Capture<Function<InternalPortStatusEvent, byte[]>> actualEncoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700673
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700674 assertTrue(actualEvent.hasCaptured());
675 assertTrue(actualSubject.hasCaptured());
676 assertTrue(actualEncoder.hasCaptured());
677
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700678 assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700679 actualSubject.getValue());
680 assertEquals(did, actualEvent.getValue().deviceId());
681 assertEquals(pid, actualEvent.getValue().providerId());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700682 assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700683 actualEvent.getValue().portDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700684 }
685
686 private void assertPortDescriptionEquals(
687 PortDescription expectedDesc,
688 List<SparseAnnotations> expectedAnnotations,
689 PortDescription actual) {
690
691 assertEquals(expectedDesc.portNumber(), actual.portNumber());
692 assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
693
694 assertAnnotationsEquals(actual.annotations(),
695 expectedAnnotations.toArray(new SparseAnnotations[0]));
696 }
697
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700698 private <T> void resetCommunicatorExpectingNoBroadcast(
699 Capture<T> message,
700 Capture<MessageSubject> subject,
701 Capture<Function<T, byte[]>> encoder) {
702 message.reset();
703 subject.reset();
704 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700705 reset(clusterCommunicator);
706 replay(clusterCommunicator);
707 }
708
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700709 private <T> void resetCommunicatorExpectingSingleBroadcast(
710 Capture<T> message,
711 Capture<MessageSubject> subject,
712 Capture<Function<T, byte[]>> encoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700713
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700714 message.reset();
715 subject.reset();
716 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700717 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700718 clusterCommunicator.broadcast(
719 capture(message),
720 capture(subject),
721 capture(encoder));
722 expectLastCall().once();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700723 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700724 }
725
726 @Test
727 public final void testGetPorts() {
728 putDevice(DID1, SW1);
729 putDevice(DID2, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700730 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700731 new DefaultPortDescription(P1, true),
732 new DefaultPortDescription(P2, true)
733 );
734 deviceStore.updatePorts(PID, DID1, pds);
735
736 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
737 List<Port> ports = deviceStore.getPorts(DID1);
738 for (Port port : ports) {
739 assertTrue("Port is enabled", port.isEnabled());
740 assertTrue("PortNumber is one of expected",
741 expectedPorts.remove(port.number()));
742 }
743 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
744
745
746 assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
747 }
748
749 @Test
750 public final void testGetPort() {
751 putDevice(DID1, SW1);
752 putDevice(DID2, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700753 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700754 new DefaultPortDescription(P1, true),
755 new DefaultPortDescription(P2, false)
756 );
757 deviceStore.updatePorts(PID, DID1, pds);
758
759 Port port1 = deviceStore.getPort(DID1, P1);
760 assertEquals(P1, port1.number());
761 assertTrue("Port is enabled", port1.isEnabled());
762
763 Port port2 = deviceStore.getPort(DID1, P2);
764 assertEquals(P2, port2.number());
765 assertFalse("Port is disabled", port2.isEnabled());
766
767 Port port3 = deviceStore.getPort(DID1, P3);
768 assertNull("P3 not expected", port3);
769 }
770
771 @Test
772 public final void testRemoveDevice() {
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700773 putDevice(DID1, SW1, A1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700774 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700775 new DefaultPortDescription(P1, true, A2)
776 );
777 deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700778 putDevice(DID2, SW1);
779
780 assertEquals(2, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700781 assertEquals(1, deviceStore.getPorts(DID1).size());
782 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
783 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700784
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700785 Capture<InternalDeviceEvent> message = new Capture<>();
786 Capture<MessageSubject> subject = new Capture<>();
787 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700788
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700789 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700790
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700791 DeviceEvent event = deviceStore.removeDevice(DID1);
792 assertEquals(DEVICE_REMOVED, event.type());
793 assertDevice(DID1, SW1, event.subject());
794
795 assertEquals(1, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700796 assertEquals(0, deviceStore.getPorts(DID1).size());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700797 verify(clusterCommunicator);
798 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700799 assertTrue(message.hasCaptured());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700800
801 // putBack Device, Port w/o annotation
802 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700803 List<PortDescription> pds2 = Arrays.asList(
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700804 new DefaultPortDescription(P1, true)
805 );
806 deviceStore.updatePorts(PID, DID1, pds2);
807
808 // annotations should not survive
809 assertEquals(2, deviceStore.getDeviceCount());
810 assertEquals(1, deviceStore.getPorts(DID1).size());
811 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations());
812 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700813 }
814
815 // If Delegates should be called only on remote events,
816 // then Simple* should never call them, thus not test required.
817 // TODO add test for Port events when we have them
818 @Ignore("Ignore until Delegate spec. is clear.")
819 @Test
820 public final void testEvents() throws InterruptedException {
821 final CountDownLatch addLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700822 DeviceStoreDelegate checkAdd = event -> {
823 assertEquals(DEVICE_ADDED, event.type());
824 assertDevice(DID1, SW1, event.subject());
825 addLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700826 };
827 final CountDownLatch updateLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700828 DeviceStoreDelegate checkUpdate = event -> {
829 assertEquals(DEVICE_UPDATED, event.type());
830 assertDevice(DID1, SW2, event.subject());
831 updateLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700832 };
833 final CountDownLatch removeLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700834 DeviceStoreDelegate checkRemove = event -> {
835 assertEquals(DEVICE_REMOVED, event.type());
836 assertDevice(DID1, SW2, event.subject());
837 removeLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700838 };
839
840 DeviceDescription description =
841 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700842 HW, SW1, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700843 deviceStore.setDelegate(checkAdd);
844 deviceStore.createOrUpdateDevice(PID, DID1, description);
845 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
846
847
848 DeviceDescription description2 =
849 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700850 HW, SW2, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700851 deviceStore.unsetDelegate(checkAdd);
852 deviceStore.setDelegate(checkUpdate);
853 deviceStore.createOrUpdateDevice(PID, DID1, description2);
854 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
855
856 deviceStore.unsetDelegate(checkUpdate);
857 deviceStore.setDelegate(checkRemove);
858 deviceStore.removeDevice(DID1);
859 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
860 }
861
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700862 private final class TestMastershipService extends MastershipServiceAdapter {
863 @Override
864 public NodeId getMasterFor(DeviceId deviceId) {
865 return NID1;
866 }
Madan Jampanic6e574f2015-05-29 13:41:52 -0700867 @Override
868 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
869 return CompletableFuture.completedFuture(null);
870 }
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700871 }
872
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700873 private static final class TestGossipDeviceStore extends GossipDeviceStore {
874
Madan Jampani53e44e62014-10-07 12:39:51 -0700875 public TestGossipDeviceStore(
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700876 DeviceClockService deviceClockService,
Madan Jampani53e44e62014-10-07 12:39:51 -0700877 ClusterService clusterService,
878 ClusterCommunicationService clusterCommunicator) {
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700879 this.deviceClockService = deviceClockService;
Madan Jampani53e44e62014-10-07 12:39:51 -0700880 this.clusterService = clusterService;
Madan Jampani47c93732014-10-06 20:46:08 -0700881 this.clusterCommunicator = clusterCommunicator;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700882 }
Madan Jampani47c93732014-10-06 20:46:08 -0700883 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700884
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800885 private static final class TestClusterService extends StaticClusterService {
Madan Jampani53e44e62014-10-07 12:39:51 -0700886
887 public TestClusterService() {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800888 localNode = ONOS1;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700889 nodes.put(NID1, ONOS1);
890 nodeStates.put(NID1, ACTIVE);
891
892 nodes.put(NID2, ONOS2);
893 nodeStates.put(NID2, ACTIVE);
Madan Jampani53e44e62014-10-07 12:39:51 -0700894 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700895 }
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700896
Madan Jampani565a66a2015-07-25 17:01:13 -0700897 private final class TestDeviceClockService extends DeviceClockServiceAdapter {
898
899 private final AtomicLong ticker = new AtomicLong();
900
901 @Override
902 public Timestamp getTimestamp(DeviceId deviceId) {
903 if (DID1.equals(deviceId)) {
904 return new MastershipBasedTimestamp(1, ticker.getAndIncrement());
905 } else if (DID2.equals(deviceId)) {
906 return new MastershipBasedTimestamp(2, ticker.getAndIncrement());
907 } else {
908 throw new IllegalStateException();
909 }
910 }
911
912 @Override
913 public boolean isTimestampAvailable(DeviceId deviceId) {
914 return DID1.equals(deviceId) || DID2.equals(deviceId);
915 }
916 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700917}