blob: 370c1d558fa2ef4dd2accd4f446ce2ca414fc772 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -070020import org.easymock.Capture;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070021import 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.ChassisId;
28import org.onlab.packet.IpAddress;
Madan Jampanif4c88502016-01-21 12:35:36 -080029import org.onlab.util.KryoNamespace;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.cluster.ClusterService;
31import org.onosproject.cluster.ControllerNode;
32import org.onosproject.cluster.DefaultControllerNode;
33import org.onosproject.cluster.NodeId;
34import org.onosproject.mastership.MastershipServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.Annotations;
36import org.onosproject.net.DefaultAnnotations;
37import org.onosproject.net.Device;
38import org.onosproject.net.DeviceId;
Madan Jampanic6e574f2015-05-29 13:41:52 -070039import org.onosproject.net.MastershipRole;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.Port;
41import org.onosproject.net.PortNumber;
42import org.onosproject.net.SparseAnnotations;
43import org.onosproject.net.device.DefaultDeviceDescription;
44import org.onosproject.net.device.DefaultPortDescription;
45import org.onosproject.net.device.DeviceClockService;
Madan Jampani565a66a2015-07-25 17:01:13 -070046import org.onosproject.net.device.DeviceClockServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.device.DeviceDescription;
48import org.onosproject.net.device.DeviceEvent;
49import org.onosproject.net.device.DeviceStore;
50import org.onosproject.net.device.DeviceStoreDelegate;
51import org.onosproject.net.device.PortDescription;
52import org.onosproject.net.provider.ProviderId;
Madan Jampani565a66a2015-07-25 17:01:13 -070053import org.onosproject.store.Timestamp;
Brian O'Connorabafb502014-12-02 22:26:20 -080054import org.onosproject.store.cluster.StaticClusterService;
55import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
56import org.onosproject.store.cluster.messaging.ClusterMessage;
Brian O'Connorabafb502014-12-02 22:26:20 -080057import org.onosproject.store.cluster.messaging.MessageSubject;
Madan Jampani565a66a2015-07-25 17:01:13 -070058import org.onosproject.store.impl.MastershipBasedTimestamp;
Madan Jampanif4c88502016-01-21 12:35:36 -080059import org.onosproject.store.service.EventuallyConsistentMap;
60import org.onosproject.store.service.EventuallyConsistentMapBuilder;
61import org.onosproject.store.service.StorageService;
Jonathan Hart46ab5cc2016-09-15 15:42:39 -070062
Jonathan Hart7d656f42015-01-27 14:07:23 -080063import java.io.IOException;
64import java.util.Arrays;
65import java.util.Collections;
66import java.util.HashMap;
67import java.util.List;
68import java.util.Map;
69import java.util.Set;
Madan Jampanic6e574f2015-05-29 13:41:52 -070070import java.util.concurrent.CompletableFuture;
Jonathan Hart7d656f42015-01-27 14:07:23 -080071import java.util.concurrent.CountDownLatch;
72import java.util.concurrent.TimeUnit;
Madan Jampani565a66a2015-07-25 17:01:13 -070073import java.util.concurrent.atomic.AtomicLong;
Madan Jampanif4c88502016-01-21 12:35:36 -080074import java.util.function.BiFunction;
Madan Jampani2bfa94c2015-04-11 05:03:49 -070075import java.util.function.Function;
Jonathan Hart7d656f42015-01-27 14:07:23 -080076
77import static java.util.Arrays.asList;
Jonathan Hart46ab5cc2016-09-15 15:42:39 -070078import static org.easymock.EasyMock.anyObject;
79import static org.easymock.EasyMock.capture;
80import static org.easymock.EasyMock.createNiceMock;
81import static org.easymock.EasyMock.expect;
82import static org.easymock.EasyMock.expectLastCall;
83import static org.easymock.EasyMock.replay;
84import static org.easymock.EasyMock.reset;
85import static org.easymock.EasyMock.verify;
86import static org.junit.Assert.assertEquals;
87import static org.junit.Assert.assertFalse;
88import static org.junit.Assert.assertNotNull;
89import static org.junit.Assert.assertNull;
90import static org.junit.Assert.assertTrue;
91import static org.junit.Assert.fail;
Jonathan Hart7d656f42015-01-27 14:07:23 -080092import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
93import static org.onosproject.net.DefaultAnnotations.union;
94import static org.onosproject.net.Device.Type.SWITCH;
95import static org.onosproject.net.DeviceId.deviceId;
Jonathan Hart46ab5cc2016-09-15 15:42:39 -070096import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
97import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
98import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
99import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED;
100import static org.onosproject.net.device.DeviceEvent.Type.PORT_ADDED;
101import static org.onosproject.net.device.DeviceEvent.Type.PORT_REMOVED;
102import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700103
104
105// TODO add tests for remote replication
106/**
107 * Test of the gossip based distributed DeviceStore implementation.
108 */
109public class GossipDeviceStoreTest {
110
111 private static final ProviderId PID = new ProviderId("of", "foo");
112 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
113 private static final DeviceId DID1 = deviceId("of:foo");
114 private static final DeviceId DID2 = deviceId("of:bar");
115 private static final String MFR = "whitebox";
116 private static final String HW = "1.1.x";
117 private static final String SW1 = "3.8.1";
118 private static final String SW2 = "3.9.5";
119 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -0700120 private static final ChassisId CID = new ChassisId();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700121
122 private static final PortNumber P1 = PortNumber.portNumber(1);
123 private static final PortNumber P2 = PortNumber.portNumber(2);
124 private static final PortNumber P3 = PortNumber.portNumber(3);
125
126 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
127 .set("A1", "a1")
128 .set("B1", "b1")
129 .build();
130 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
131 .remove("A1")
132 .set("B3", "b3")
133 .build();
134 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
135 .set("A2", "a2")
136 .set("B2", "b2")
137 .build();
138 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
139 .remove("A2")
140 .set("B4", "b4")
141 .build();
142
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700143 // local node
144 private static final NodeId NID1 = new NodeId("local");
145 private static final ControllerNode ONOS1 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700146 new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1"));
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700147
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700148 // remote node
149 private static final NodeId NID2 = new NodeId("remote");
150 private static final ControllerNode ONOS2 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700151 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700152 private static final List<SparseAnnotations> NO_ANNOTATION = Collections.emptyList();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700153
Madan Jampanif4c88502016-01-21 12:35:36 -0800154 EventuallyConsistentMapBuilder ecMapBuilder;
155 EventuallyConsistentMap ecMap;
156 StorageService testStorageService;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700157 private TestGossipDeviceStore testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700158 private GossipDeviceStore gossipDeviceStore;
159 private DeviceStore deviceStore;
160
Madan Jampani565a66a2015-07-25 17:01:13 -0700161 private DeviceClockService deviceClockService = new TestDeviceClockService();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700162 private ClusterCommunicationService clusterCommunicator;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800163
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700164 @BeforeClass
165 public static void setUpBeforeClass() throws Exception {
166 }
167
168 @AfterClass
169 public static void tearDownAfterClass() throws Exception {
170 }
171
172
173 @Before
174 public void setUp() throws Exception {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700175 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700176 replay(clusterCommunicator);
Madan Jampani53e44e62014-10-07 12:39:51 -0700177 ClusterService clusterService = new TestClusterService();
Madan Jampani47c93732014-10-06 20:46:08 -0700178
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700179 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700180 testGossipDeviceStore.mastershipService = new TestMastershipService();
181
Madan Jampanif4c88502016-01-21 12:35:36 -0800182 ecMapBuilder = createNiceMock(EventuallyConsistentMapBuilder.class);
183 expect(ecMapBuilder.withName(anyObject(String.class))).andReturn(ecMapBuilder).anyTimes();
184 expect(ecMapBuilder.withSerializer(anyObject(KryoNamespace.Builder.class))).andReturn(ecMapBuilder).anyTimes();
185 expect(ecMapBuilder.withAntiEntropyPeriod(5, TimeUnit.SECONDS)).andReturn(ecMapBuilder).anyTimes();
186 expect(ecMapBuilder.withTimestampProvider(anyObject(BiFunction.class))).andReturn(ecMapBuilder).anyTimes();
187 expect(ecMapBuilder.withTombstonesDisabled()).andReturn(ecMapBuilder).anyTimes();
188
189 ecMap = createNiceMock(EventuallyConsistentMap.class);
190 expect(ecMapBuilder.build()).andReturn(ecMap).anyTimes();
191 testStorageService = createNiceMock(StorageService.class);
192 expect(testStorageService.eventuallyConsistentMapBuilder()).andReturn(ecMapBuilder).anyTimes();
193
194 replay(testStorageService, ecMapBuilder, ecMap);
195
196 testGossipDeviceStore.storageService = testStorageService;
Madan Jampani565a66a2015-07-25 17:01:13 -0700197 testGossipDeviceStore.deviceClockService = deviceClockService;
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700198
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700199 gossipDeviceStore = testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700200 gossipDeviceStore.activate();
201 deviceStore = gossipDeviceStore;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700202 verify(clusterCommunicator);
203 reset(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700204 }
205
206 @After
207 public void tearDown() throws Exception {
208 gossipDeviceStore.deactivate();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700209 }
210
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700211 private void putDevice(DeviceId deviceId, String swVersion,
212 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700213 DeviceDescription description =
214 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700215 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700216 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700217 clusterCommunicator.<InternalDeviceEvent>broadcast(
218 anyObject(InternalDeviceEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
219 expectLastCall().anyTimes();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700220 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700221 deviceStore.createOrUpdateDevice(PID, deviceId, description);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700222 verify(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700223 }
224
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700225 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
226 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700227 DeviceDescription description =
228 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700229 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700230 deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
231 }
232
233 private static void assertDevice(DeviceId id, String swVersion, Device device) {
234 assertNotNull(device);
235 assertEquals(id, device.id());
236 assertEquals(MFR, device.manufacturer());
237 assertEquals(HW, device.hwVersion());
238 assertEquals(swVersion, device.swVersion());
239 assertEquals(SN, device.serialNumber());
240 }
241
242 /**
243 * Verifies that Annotations created by merging {@code annotations} is
244 * equal to actual Annotations.
245 *
246 * @param actual Annotations to check
247 * @param annotations
248 */
249 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700250 SparseAnnotations expected = DefaultAnnotations.builder().build();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700251 for (SparseAnnotations a : annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700252 expected = DefaultAnnotations.union(expected, a);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700253 }
254 assertEquals(expected.keys(), actual.keys());
255 for (String key : expected.keys()) {
256 assertEquals(expected.value(key), actual.value(key));
257 }
258 }
259
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700260 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
261 DeviceDescription actual) {
262 if (expected == actual) {
263 return;
264 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800265 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700266 assertEquals(expected.hwVersion(), actual.hwVersion());
267 assertEquals(expected.manufacturer(), actual.manufacturer());
268 assertEquals(expected.serialNumber(), actual.serialNumber());
269 assertEquals(expected.swVersion(), actual.swVersion());
270
271 assertAnnotationsEquals(actual.annotations(), expected.annotations());
272 }
273
274 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
275 List<SparseAnnotations> expectedAnnotations,
276 DeviceDescription actual) {
277 if (expected == actual) {
278 return;
279 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800280 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700281 assertEquals(expected.hwVersion(), actual.hwVersion());
282 assertEquals(expected.manufacturer(), actual.manufacturer());
283 assertEquals(expected.serialNumber(), actual.serialNumber());
284 assertEquals(expected.swVersion(), actual.swVersion());
285
286 assertAnnotationsEquals(actual.annotations(),
287 expectedAnnotations.toArray(new SparseAnnotations[0]));
288 }
289
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700290 @Test
291 public final void testGetDeviceCount() {
292 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
293
294 putDevice(DID1, SW1);
295 putDevice(DID2, SW2);
296 putDevice(DID1, SW1);
297
298 assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
299 }
300
301 @Test
mskala0d0c6832017-07-12 11:21:23 +0200302 public final void testGetAvailableDeviceCount() {
303 assertEquals("initialy empty", 0, deviceStore.getAvailableDeviceCount());
304
305 putDevice(DID1, SW1);
306 putDevice(DID2, SW2);
307
308 deviceStore.markOffline(DID1);
309
310 assertEquals("expect 1 available device", 1, deviceStore.getAvailableDeviceCount());
311
312 deviceStore.markOnline(DID1);
313
314 assertEquals("expect 2 available devices", 2, deviceStore.getAvailableDeviceCount());
315 }
316
317 @Test
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700318 public final void testGetDevices() {
319 assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
320
321 putDevice(DID1, SW1);
322 putDevice(DID2, SW2);
323 putDevice(DID1, SW1);
324
325 assertEquals("expect 2 uniq devices",
326 2, Iterables.size(deviceStore.getDevices()));
327
328 Map<DeviceId, Device> devices = new HashMap<>();
329 for (Device device : deviceStore.getDevices()) {
330 devices.put(device.id(), device);
331 }
332
333 assertDevice(DID1, SW1, devices.get(DID1));
334 assertDevice(DID2, SW2, devices.get(DID2));
335
336 // add case for new node?
337 }
338
339 @Test
340 public final void testGetDevice() {
341
342 putDevice(DID1, SW1);
343
344 assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
345 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
346 }
347
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700348 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700349 DeviceId deviceId,
350 ProviderId providerId,
351 DeviceDescription expectedDesc,
352 Capture<InternalDeviceEvent> actualEvent,
353 Capture<MessageSubject> actualSubject,
354 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
355 assertTrue(actualEvent.hasCaptured());
356 assertTrue(actualSubject.hasCaptured());
357 assertTrue(actualEncoder.hasCaptured());
358
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700359 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700360 actualSubject.getValue());
361 assertEquals(deviceId, actualEvent.getValue().deviceId());
362 assertEquals(providerId, actualEvent.getValue().providerId());
363 assertDeviceDescriptionEquals(expectedDesc, actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700364 }
365
366 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700367 DeviceId deviceId,
368 ProviderId providerId,
369 DeviceDescription expectedDesc,
370 List<SparseAnnotations> expectedAnnotations,
371 Capture<InternalDeviceEvent> actualEvent,
372 Capture<MessageSubject> actualSubject,
373 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
374 assertTrue(actualEvent.hasCaptured());
375 assertTrue(actualSubject.hasCaptured());
376 assertTrue(actualEncoder.hasCaptured());
377
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700378 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700379 actualSubject.getValue());
380 assertEquals(deviceId, actualEvent.getValue().deviceId());
381 assertEquals(providerId, actualEvent.getValue().providerId());
382 assertDeviceDescriptionEquals(
383 expectedDesc,
384 expectedAnnotations,
385 actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700386 }
387
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700388 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700389 public final void testCreateOrUpdateDevice() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700390 DeviceDescription description =
391 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700392 HW, SW1, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700393 Capture<InternalDeviceEvent> message = new Capture<>();
394 Capture<MessageSubject> subject = new Capture<>();
395 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700396
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700397 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700398 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
399 assertEquals(DEVICE_ADDED, event.type());
400 assertDevice(DID1, SW1, event.subject());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700401 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700402 assertInternalDeviceEvent(NID1, DID1, PID, description, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700403
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700404
405 DeviceDescription description2 =
406 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700407 HW, SW2, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700408 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700409 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
410 assertEquals(DEVICE_UPDATED, event2.type());
411 assertDevice(DID1, SW2, event2.subject());
412
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700413 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700414 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700415 reset(clusterCommunicator);
416
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700417 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
418 }
419
420 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700421 public final void testCreateOrUpdateDeviceAncillary() throws IOException {
422 // add
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700423 DeviceDescription description =
424 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700425 HW, SW1, SN, CID, A2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700426 Capture<ClusterMessage> bcast = new Capture<>();
427
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700428 Capture<InternalDeviceEvent> message = new Capture<>();
429 Capture<MessageSubject> subject = new Capture<>();
430 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
431
432 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700433 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
434 assertEquals(DEVICE_ADDED, event.type());
435 assertDevice(DID1, SW1, event.subject());
436 assertEquals(PIDA, event.subject().providerId());
437 assertAnnotationsEquals(event.subject().annotations(), A2);
438 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700439 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700440 assertInternalDeviceEvent(NID1, DID1, PIDA, description, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700441
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700442 // update from primary
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700443 DeviceDescription description2 =
444 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700445 HW, SW2, SN, CID, A1);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700446 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700447
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700448 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
449 assertEquals(DEVICE_UPDATED, event2.type());
450 assertDevice(DID1, SW2, event2.subject());
451 assertEquals(PID, event2.subject().providerId());
452 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
453 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700454 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700455 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700456
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700457 // no-op update from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700458 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700459 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
460
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700461 verify(clusterCommunicator);
462 assertFalse("no broadcast expected", bcast.hasCaptured());
463
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700464 // For now, Ancillary is ignored once primary appears
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700465 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700466
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700467 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
468
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700469 verify(clusterCommunicator);
470 assertFalse("no broadcast expected", bcast.hasCaptured());
471
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700472 // But, Ancillary annotations will be in effect
473 DeviceDescription description3 =
474 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700475 HW, SW1, SN, CID, A2_2);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700476 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700477
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700478 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
479 assertEquals(DEVICE_UPDATED, event3.type());
480 // basic information will be the one from Primary
481 assertDevice(DID1, SW2, event3.subject());
482 assertEquals(PID, event3.subject().providerId());
483 // but annotation from Ancillary will be merged
484 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
485 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700486 verify(clusterCommunicator);
487 // note: only annotation from PIDA is sent over the wire
488 assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700489 asList(union(A2, A2_2)), message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700490
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700491 }
492
493
494 @Test
495 public final void testMarkOffline() {
496
497 putDevice(DID1, SW1);
498 assertTrue(deviceStore.isAvailable(DID1));
499
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700500 Capture<InternalDeviceEvent> message = new Capture<>();
501 Capture<MessageSubject> subject = new Capture<>();
502 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700503
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700504 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700505 DeviceEvent event = deviceStore.markOffline(DID1);
506 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
507 assertDevice(DID1, SW1, event.subject());
508 assertFalse(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700509 verify(clusterCommunicator);
510 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700511 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700512
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700513
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700514 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700515 DeviceEvent event2 = deviceStore.markOffline(DID1);
516 assertNull("No change, no event", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700517 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700518 assertFalse(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700519 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700520
521 @Test
522 public final void testUpdatePorts() {
523 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700524 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700525 new DefaultPortDescription(P1, true),
526 new DefaultPortDescription(P2, true)
527 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700528 Capture<InternalDeviceEvent> message = new Capture<>();
529 Capture<MessageSubject> subject = new Capture<>();
530 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700531
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700532 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700533 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700534 verify(clusterCommunicator);
535 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700536 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700537
538 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
539 for (DeviceEvent event : events) {
540 assertEquals(PORT_ADDED, event.type());
541 assertDevice(DID1, SW1, event.subject());
542 assertTrue("PortNumber is one of expected",
543 expectedPorts.remove(event.port().number()));
544 assertTrue("Port is enabled", event.port().isEnabled());
545 }
546 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
547
548
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700549 List<PortDescription> pds2 = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700550 new DefaultPortDescription(P1, false),
551 new DefaultPortDescription(P2, true),
552 new DefaultPortDescription(P3, true)
553 );
554
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700555 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700556 events = deviceStore.updatePorts(PID, DID1, pds2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700557 verify(clusterCommunicator);
558 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700559 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700560
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700561 assertFalse("event should be triggered", events.isEmpty());
562 for (DeviceEvent event : events) {
563 PortNumber num = event.port().number();
564 if (P1.equals(num)) {
565 assertEquals(PORT_UPDATED, event.type());
566 assertDevice(DID1, SW1, event.subject());
567 assertFalse("Port is disabled", event.port().isEnabled());
568 } else if (P2.equals(num)) {
569 fail("P2 event not expected.");
570 } else if (P3.equals(num)) {
571 assertEquals(PORT_ADDED, event.type());
572 assertDevice(DID1, SW1, event.subject());
573 assertTrue("Port is enabled", event.port().isEnabled());
574 } else {
575 fail("Unknown port number encountered: " + num);
576 }
577 }
578
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700579 List<PortDescription> pds3 = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700580 new DefaultPortDescription(P1, false),
581 new DefaultPortDescription(P2, true)
582 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700583 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700584 events = deviceStore.updatePorts(PID, DID1, pds3);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700585 verify(clusterCommunicator);
586 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700587 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700588
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700589 assertFalse("event should be triggered", events.isEmpty());
590 for (DeviceEvent event : events) {
591 PortNumber num = event.port().number();
592 if (P1.equals(num)) {
593 fail("P1 event not expected.");
594 } else if (P2.equals(num)) {
595 fail("P2 event not expected.");
596 } else if (P3.equals(num)) {
597 assertEquals(PORT_REMOVED, event.type());
598 assertDevice(DID1, SW1, event.subject());
599 assertTrue("Port was enabled", event.port().isEnabled());
600 } else {
601 fail("Unknown port number encountered: " + num);
602 }
603 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700604 }
605
606 @Test
607 public final void testUpdatePortStatus() {
608 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700609 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700610 new DefaultPortDescription(P1, true)
611 );
612 deviceStore.updatePorts(PID, DID1, pds);
613
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700614 Capture<InternalPortStatusEvent> message = new Capture<>();
615 Capture<MessageSubject> subject = new Capture<>();
616 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700617
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700618 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700619 final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
620 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700621 assertEquals(PORT_UPDATED, event.type());
622 assertDevice(DID1, SW1, event.subject());
623 assertEquals(P1, event.port().number());
624 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700625 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700626 assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, message, subject, encoder);
627 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700628 }
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700629
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700630 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700631 public final void testUpdatePortStatusAncillary() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700632 putDeviceAncillary(DID1, SW1);
633 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700634 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700635 new DefaultPortDescription(P1, true, A1)
636 );
637 deviceStore.updatePorts(PID, DID1, pds);
638
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700639 Capture<InternalPortStatusEvent> message = new Capture<>();
640 Capture<MessageSubject> subject = new Capture<>();
641 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700642
643 // update port from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700644 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
645
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700646 final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
647 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700648 assertEquals(PORT_UPDATED, event.type());
649 assertDevice(DID1, SW1, event.subject());
650 assertEquals(P1, event.port().number());
651 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
652 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700653 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700654 assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), message, subject, encoder);
655 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700656
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700657 // update port from ancillary with no attributes
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700658 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700659 final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
660 DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700661 assertNull("Ancillary is ignored if primary exists", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700662 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700663 assertFalse(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700664
665 // but, Ancillary annotation update will be notified
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700666 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700667 final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
668 DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700669 assertEquals(PORT_UPDATED, event3.type());
670 assertDevice(DID1, SW1, event3.subject());
671 assertEquals(P1, event3.port().number());
672 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
673 assertFalse("Port is disabled", event3.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700674 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700675 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), message, subject, encoder);
676 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700677
678 // port only reported from Ancillary will be notified as down
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700679 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700680 final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
681 DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700682 assertEquals(PORT_ADDED, event4.type());
683 assertDevice(DID1, SW1, event4.subject());
684 assertEquals(P2, event4.port().number());
685 assertAnnotationsEquals(event4.port().annotations());
686 assertFalse("Port is disabled if not given from primary provider",
687 event4.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700688 verify(clusterCommunicator);
689 // TODO: verify broadcast message content
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700690 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, message, subject, encoder);
691 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700692 }
693
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700694 private void assertInternalPortStatusEvent(NodeId sender,
695 DeviceId did,
696 ProviderId pid,
697 DefaultPortDescription expectedDesc,
698 List<SparseAnnotations> expectedAnnotations,
699 Capture<InternalPortStatusEvent> actualEvent,
700 Capture<MessageSubject> actualSubject,
701 Capture<Function<InternalPortStatusEvent, byte[]>> actualEncoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700702
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700703 assertTrue(actualEvent.hasCaptured());
704 assertTrue(actualSubject.hasCaptured());
705 assertTrue(actualEncoder.hasCaptured());
706
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700707 assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700708 actualSubject.getValue());
709 assertEquals(did, actualEvent.getValue().deviceId());
710 assertEquals(pid, actualEvent.getValue().providerId());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700711 assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700712 actualEvent.getValue().portDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700713 }
714
715 private void assertPortDescriptionEquals(
716 PortDescription expectedDesc,
717 List<SparseAnnotations> expectedAnnotations,
718 PortDescription actual) {
719
720 assertEquals(expectedDesc.portNumber(), actual.portNumber());
721 assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
722
723 assertAnnotationsEquals(actual.annotations(),
724 expectedAnnotations.toArray(new SparseAnnotations[0]));
725 }
726
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700727 private <T> void resetCommunicatorExpectingNoBroadcast(
728 Capture<T> message,
729 Capture<MessageSubject> subject,
730 Capture<Function<T, byte[]>> encoder) {
731 message.reset();
732 subject.reset();
733 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700734 reset(clusterCommunicator);
735 replay(clusterCommunicator);
736 }
737
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700738 private <T> void resetCommunicatorExpectingSingleBroadcast(
739 Capture<T> message,
740 Capture<MessageSubject> subject,
741 Capture<Function<T, byte[]>> encoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700742
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700743 message.reset();
744 subject.reset();
745 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700746 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700747 clusterCommunicator.broadcast(
748 capture(message),
749 capture(subject),
750 capture(encoder));
751 expectLastCall().once();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700752 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700753 }
754
755 @Test
756 public final void testGetPorts() {
757 putDevice(DID1, SW1);
758 putDevice(DID2, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700759 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700760 new DefaultPortDescription(P1, true),
761 new DefaultPortDescription(P2, true)
762 );
763 deviceStore.updatePorts(PID, DID1, pds);
764
765 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
766 List<Port> ports = deviceStore.getPorts(DID1);
767 for (Port port : ports) {
768 assertTrue("Port is enabled", port.isEnabled());
769 assertTrue("PortNumber is one of expected",
770 expectedPorts.remove(port.number()));
771 }
772 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
773
774
775 assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
776 }
777
778 @Test
779 public final void testGetPort() {
780 putDevice(DID1, SW1);
781 putDevice(DID2, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700782 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700783 new DefaultPortDescription(P1, true),
784 new DefaultPortDescription(P2, false)
785 );
786 deviceStore.updatePorts(PID, DID1, pds);
787
788 Port port1 = deviceStore.getPort(DID1, P1);
789 assertEquals(P1, port1.number());
790 assertTrue("Port is enabled", port1.isEnabled());
791
792 Port port2 = deviceStore.getPort(DID1, P2);
793 assertEquals(P2, port2.number());
794 assertFalse("Port is disabled", port2.isEnabled());
795
796 Port port3 = deviceStore.getPort(DID1, P3);
797 assertNull("P3 not expected", port3);
798 }
799
800 @Test
801 public final void testRemoveDevice() {
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700802 putDevice(DID1, SW1, A1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700803 List<PortDescription> pds = Arrays.asList(
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700804 new DefaultPortDescription(P1, true, A2)
805 );
806 deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700807 putDevice(DID2, SW1);
808
809 assertEquals(2, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700810 assertEquals(1, deviceStore.getPorts(DID1).size());
811 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
812 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700813
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700814 Capture<InternalDeviceEvent> message = new Capture<>();
815 Capture<MessageSubject> subject = new Capture<>();
816 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700817
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700818 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700819
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700820 DeviceEvent event = deviceStore.removeDevice(DID1);
821 assertEquals(DEVICE_REMOVED, event.type());
822 assertDevice(DID1, SW1, event.subject());
823
824 assertEquals(1, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700825 assertEquals(0, deviceStore.getPorts(DID1).size());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700826 verify(clusterCommunicator);
827 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700828 assertTrue(message.hasCaptured());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700829
830 // putBack Device, Port w/o annotation
831 putDevice(DID1, SW1);
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700832 List<PortDescription> pds2 = Arrays.asList(
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700833 new DefaultPortDescription(P1, true)
834 );
835 deviceStore.updatePorts(PID, DID1, pds2);
836
837 // annotations should not survive
838 assertEquals(2, deviceStore.getDeviceCount());
839 assertEquals(1, deviceStore.getPorts(DID1).size());
840 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations());
841 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700842 }
843
844 // If Delegates should be called only on remote events,
845 // then Simple* should never call them, thus not test required.
846 // TODO add test for Port events when we have them
847 @Ignore("Ignore until Delegate spec. is clear.")
848 @Test
849 public final void testEvents() throws InterruptedException {
850 final CountDownLatch addLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700851 DeviceStoreDelegate checkAdd = event -> {
852 assertEquals(DEVICE_ADDED, event.type());
853 assertDevice(DID1, SW1, event.subject());
854 addLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700855 };
856 final CountDownLatch updateLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700857 DeviceStoreDelegate checkUpdate = event -> {
858 assertEquals(DEVICE_UPDATED, event.type());
859 assertDevice(DID1, SW2, event.subject());
860 updateLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700861 };
862 final CountDownLatch removeLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700863 DeviceStoreDelegate checkRemove = event -> {
864 assertEquals(DEVICE_REMOVED, event.type());
865 assertDevice(DID1, SW2, event.subject());
866 removeLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700867 };
868
869 DeviceDescription description =
870 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700871 HW, SW1, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700872 deviceStore.setDelegate(checkAdd);
873 deviceStore.createOrUpdateDevice(PID, DID1, description);
874 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
875
876
877 DeviceDescription description2 =
878 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700879 HW, SW2, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700880 deviceStore.unsetDelegate(checkAdd);
881 deviceStore.setDelegate(checkUpdate);
882 deviceStore.createOrUpdateDevice(PID, DID1, description2);
883 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
884
885 deviceStore.unsetDelegate(checkUpdate);
886 deviceStore.setDelegate(checkRemove);
887 deviceStore.removeDevice(DID1);
888 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
889 }
890
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700891 private final class TestMastershipService extends MastershipServiceAdapter {
892 @Override
893 public NodeId getMasterFor(DeviceId deviceId) {
894 return NID1;
895 }
Madan Jampanic6e574f2015-05-29 13:41:52 -0700896 @Override
897 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
898 return CompletableFuture.completedFuture(null);
899 }
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700900 }
901
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700902 private static final class TestGossipDeviceStore extends GossipDeviceStore {
903
Madan Jampani53e44e62014-10-07 12:39:51 -0700904 public TestGossipDeviceStore(
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700905 DeviceClockService deviceClockService,
Madan Jampani53e44e62014-10-07 12:39:51 -0700906 ClusterService clusterService,
907 ClusterCommunicationService clusterCommunicator) {
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700908 this.deviceClockService = deviceClockService;
Madan Jampani53e44e62014-10-07 12:39:51 -0700909 this.clusterService = clusterService;
Madan Jampani47c93732014-10-06 20:46:08 -0700910 this.clusterCommunicator = clusterCommunicator;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700911 }
Madan Jampani47c93732014-10-06 20:46:08 -0700912 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700913
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800914 private static final class TestClusterService extends StaticClusterService {
Madan Jampani53e44e62014-10-07 12:39:51 -0700915
916 public TestClusterService() {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800917 localNode = ONOS1;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700918 nodes.put(NID1, ONOS1);
919 nodeStates.put(NID1, ACTIVE);
920
921 nodes.put(NID2, ONOS2);
922 nodeStates.put(NID2, ACTIVE);
Madan Jampani53e44e62014-10-07 12:39:51 -0700923 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700924 }
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700925
Madan Jampani565a66a2015-07-25 17:01:13 -0700926 private final class TestDeviceClockService extends DeviceClockServiceAdapter {
927
928 private final AtomicLong ticker = new AtomicLong();
929
930 @Override
931 public Timestamp getTimestamp(DeviceId deviceId) {
932 if (DID1.equals(deviceId)) {
933 return new MastershipBasedTimestamp(1, ticker.getAndIncrement());
934 } else if (DID2.equals(deviceId)) {
935 return new MastershipBasedTimestamp(2, ticker.getAndIncrement());
936 } else {
937 throw new IllegalStateException();
938 }
939 }
940
941 @Override
942 public boolean isTimestampAvailable(DeviceId deviceId) {
943 return DID1.equals(deviceId) || DID2.equals(deviceId);
944 }
945 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700946}