blob: 5cbf360ab395ec248e67eb55b46e0c5db7233357 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 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;
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;
57import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
58import org.onosproject.store.cluster.messaging.MessageSubject;
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -070059import org.onosproject.store.consistent.impl.DatabaseManager;
Madan Jampani565a66a2015-07-25 17:01:13 -070060import org.onosproject.store.impl.MastershipBasedTimestamp;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070061
Jonathan Hart7d656f42015-01-27 14:07:23 -080062import java.io.IOException;
63import java.util.Arrays;
64import java.util.Collections;
65import java.util.HashMap;
66import java.util.List;
67import java.util.Map;
68import java.util.Set;
Madan Jampanic6e574f2015-05-29 13:41:52 -070069import java.util.concurrent.CompletableFuture;
Jonathan Hart7d656f42015-01-27 14:07:23 -080070import java.util.concurrent.CountDownLatch;
Madan Jampani2af244a2015-02-22 13:12:01 -080071import java.util.concurrent.ExecutorService;
Jonathan Hart7d656f42015-01-27 14:07:23 -080072import java.util.concurrent.TimeUnit;
Madan Jampani565a66a2015-07-25 17:01:13 -070073import java.util.concurrent.atomic.AtomicLong;
Madan Jampani2bfa94c2015-04-11 05:03:49 -070074import java.util.function.Function;
Jonathan Hart7d656f42015-01-27 14:07:23 -080075
76import static java.util.Arrays.asList;
77import static org.easymock.EasyMock.*;
78import static org.junit.Assert.*;
79import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
80import static org.onosproject.net.DefaultAnnotations.union;
81import static org.onosproject.net.Device.Type.SWITCH;
82import static org.onosproject.net.DeviceId.deviceId;
83import static org.onosproject.net.device.DeviceEvent.Type.*;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070084
85
86// TODO add tests for remote replication
87/**
88 * Test of the gossip based distributed DeviceStore implementation.
89 */
90public class GossipDeviceStoreTest {
91
92 private static final ProviderId PID = new ProviderId("of", "foo");
93 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
94 private static final DeviceId DID1 = deviceId("of:foo");
95 private static final DeviceId DID2 = deviceId("of:bar");
96 private static final String MFR = "whitebox";
97 private static final String HW = "1.1.x";
98 private static final String SW1 = "3.8.1";
99 private static final String SW2 = "3.9.5";
100 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -0700101 private static final ChassisId CID = new ChassisId();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700102
103 private static final PortNumber P1 = PortNumber.portNumber(1);
104 private static final PortNumber P2 = PortNumber.portNumber(2);
105 private static final PortNumber P3 = PortNumber.portNumber(3);
106
107 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
108 .set("A1", "a1")
109 .set("B1", "b1")
110 .build();
111 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
112 .remove("A1")
113 .set("B3", "b3")
114 .build();
115 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
116 .set("A2", "a2")
117 .set("B2", "b2")
118 .build();
119 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
120 .remove("A2")
121 .set("B4", "b4")
122 .build();
123
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700124 // local node
125 private static final NodeId NID1 = new NodeId("local");
126 private static final ControllerNode ONOS1 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700127 new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1"));
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700128
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700129 // remote node
130 private static final NodeId NID2 = new NodeId("remote");
131 private static final ControllerNode ONOS2 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700132 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700133 private static final List<SparseAnnotations> NO_ANNOTATION = Collections.<SparseAnnotations>emptyList();
134
135
136 private TestGossipDeviceStore testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700137 private GossipDeviceStore gossipDeviceStore;
138 private DeviceStore deviceStore;
139
Madan Jampani565a66a2015-07-25 17:01:13 -0700140 private DeviceClockService deviceClockService = new TestDeviceClockService();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700141 private ClusterCommunicationService clusterCommunicator;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800142
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700143 @BeforeClass
144 public static void setUpBeforeClass() throws Exception {
145 }
146
147 @AfterClass
148 public static void tearDownAfterClass() throws Exception {
149 }
150
151
152 @Before
153 public void setUp() throws Exception {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700154 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
155 clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700156 anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700157 expectLastCall().anyTimes();
158 replay(clusterCommunicator);
Madan Jampani53e44e62014-10-07 12:39:51 -0700159 ClusterService clusterService = new TestClusterService();
Madan Jampani47c93732014-10-06 20:46:08 -0700160
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700161 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700162 testGossipDeviceStore.mastershipService = new TestMastershipService();
163
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700164 TestDatabaseManager testDatabaseManager = new TestDatabaseManager();
165 testDatabaseManager.init(clusterService, clusterCommunicator);
166 testGossipDeviceStore.storageService = testDatabaseManager;
Madan Jampani565a66a2015-07-25 17:01:13 -0700167 testGossipDeviceStore.deviceClockService = deviceClockService;
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700168
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700169 gossipDeviceStore = testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700170 gossipDeviceStore.activate();
171 deviceStore = gossipDeviceStore;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700172 verify(clusterCommunicator);
173 reset(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700174 }
175
176 @After
177 public void tearDown() throws Exception {
178 gossipDeviceStore.deactivate();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700179 }
180
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700181 private void putDevice(DeviceId deviceId, String swVersion,
182 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700183 DeviceDescription description =
184 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700185 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700186 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700187 clusterCommunicator.<InternalDeviceEvent>broadcast(
188 anyObject(InternalDeviceEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
189 expectLastCall().anyTimes();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700190 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700191 deviceStore.createOrUpdateDevice(PID, deviceId, description);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700192 verify(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700193 }
194
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700195 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
196 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700197 DeviceDescription description =
198 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700199 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700200 deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
201 }
202
203 private static void assertDevice(DeviceId id, String swVersion, Device device) {
204 assertNotNull(device);
205 assertEquals(id, device.id());
206 assertEquals(MFR, device.manufacturer());
207 assertEquals(HW, device.hwVersion());
208 assertEquals(swVersion, device.swVersion());
209 assertEquals(SN, device.serialNumber());
210 }
211
212 /**
213 * Verifies that Annotations created by merging {@code annotations} is
214 * equal to actual Annotations.
215 *
216 * @param actual Annotations to check
217 * @param annotations
218 */
219 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700220 SparseAnnotations expected = DefaultAnnotations.builder().build();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700221 for (SparseAnnotations a : annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700222 expected = DefaultAnnotations.union(expected, a);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700223 }
224 assertEquals(expected.keys(), actual.keys());
225 for (String key : expected.keys()) {
226 assertEquals(expected.value(key), actual.value(key));
227 }
228 }
229
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700230 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
231 DeviceDescription actual) {
232 if (expected == actual) {
233 return;
234 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800235 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700236 assertEquals(expected.hwVersion(), actual.hwVersion());
237 assertEquals(expected.manufacturer(), actual.manufacturer());
238 assertEquals(expected.serialNumber(), actual.serialNumber());
239 assertEquals(expected.swVersion(), actual.swVersion());
240
241 assertAnnotationsEquals(actual.annotations(), expected.annotations());
242 }
243
244 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
245 List<SparseAnnotations> expectedAnnotations,
246 DeviceDescription actual) {
247 if (expected == actual) {
248 return;
249 }
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800250 assertEquals(expected.deviceUri(), actual.deviceUri());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700251 assertEquals(expected.hwVersion(), actual.hwVersion());
252 assertEquals(expected.manufacturer(), actual.manufacturer());
253 assertEquals(expected.serialNumber(), actual.serialNumber());
254 assertEquals(expected.swVersion(), actual.swVersion());
255
256 assertAnnotationsEquals(actual.annotations(),
257 expectedAnnotations.toArray(new SparseAnnotations[0]));
258 }
259
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700260 @Test
261 public final void testGetDeviceCount() {
262 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
263
264 putDevice(DID1, SW1);
265 putDevice(DID2, SW2);
266 putDevice(DID1, SW1);
267
268 assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
269 }
270
271 @Test
272 public final void testGetDevices() {
273 assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
274
275 putDevice(DID1, SW1);
276 putDevice(DID2, SW2);
277 putDevice(DID1, SW1);
278
279 assertEquals("expect 2 uniq devices",
280 2, Iterables.size(deviceStore.getDevices()));
281
282 Map<DeviceId, Device> devices = new HashMap<>();
283 for (Device device : deviceStore.getDevices()) {
284 devices.put(device.id(), device);
285 }
286
287 assertDevice(DID1, SW1, devices.get(DID1));
288 assertDevice(DID2, SW2, devices.get(DID2));
289
290 // add case for new node?
291 }
292
293 @Test
294 public final void testGetDevice() {
295
296 putDevice(DID1, SW1);
297
298 assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
299 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
300 }
301
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700302 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700303 DeviceId deviceId,
304 ProviderId providerId,
305 DeviceDescription expectedDesc,
306 Capture<InternalDeviceEvent> actualEvent,
307 Capture<MessageSubject> actualSubject,
308 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
309 assertTrue(actualEvent.hasCaptured());
310 assertTrue(actualSubject.hasCaptured());
311 assertTrue(actualEncoder.hasCaptured());
312
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700313 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700314 actualSubject.getValue());
315 assertEquals(deviceId, actualEvent.getValue().deviceId());
316 assertEquals(providerId, actualEvent.getValue().providerId());
317 assertDeviceDescriptionEquals(expectedDesc, actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700318 }
319
320 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700321 DeviceId deviceId,
322 ProviderId providerId,
323 DeviceDescription expectedDesc,
324 List<SparseAnnotations> expectedAnnotations,
325 Capture<InternalDeviceEvent> actualEvent,
326 Capture<MessageSubject> actualSubject,
327 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
328 assertTrue(actualEvent.hasCaptured());
329 assertTrue(actualSubject.hasCaptured());
330 assertTrue(actualEncoder.hasCaptured());
331
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700332 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700333 actualSubject.getValue());
334 assertEquals(deviceId, actualEvent.getValue().deviceId());
335 assertEquals(providerId, actualEvent.getValue().providerId());
336 assertDeviceDescriptionEquals(
337 expectedDesc,
338 expectedAnnotations,
339 actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700340 }
341
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700342 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700343 public final void testCreateOrUpdateDevice() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700344 DeviceDescription description =
345 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700346 HW, SW1, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700347 Capture<InternalDeviceEvent> message = new Capture<>();
348 Capture<MessageSubject> subject = new Capture<>();
349 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700350
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700351 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700352 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
353 assertEquals(DEVICE_ADDED, event.type());
354 assertDevice(DID1, SW1, event.subject());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700355 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700356 assertInternalDeviceEvent(NID1, DID1, PID, description, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700357
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700358
359 DeviceDescription description2 =
360 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700361 HW, SW2, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700362 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700363 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
364 assertEquals(DEVICE_UPDATED, event2.type());
365 assertDevice(DID1, SW2, event2.subject());
366
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700367 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700368 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700369 reset(clusterCommunicator);
370
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700371 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
372 }
373
374 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700375 public final void testCreateOrUpdateDeviceAncillary() throws IOException {
376 // add
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700377 DeviceDescription description =
378 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700379 HW, SW1, SN, CID, A2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700380 Capture<ClusterMessage> bcast = new Capture<>();
381
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700382 Capture<InternalDeviceEvent> message = new Capture<>();
383 Capture<MessageSubject> subject = new Capture<>();
384 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
385
386 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700387 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
388 assertEquals(DEVICE_ADDED, event.type());
389 assertDevice(DID1, SW1, event.subject());
390 assertEquals(PIDA, event.subject().providerId());
391 assertAnnotationsEquals(event.subject().annotations(), A2);
392 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700393 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700394 assertInternalDeviceEvent(NID1, DID1, PIDA, description, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700395
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700396 // update from primary
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700397 DeviceDescription description2 =
398 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700399 HW, SW2, SN, CID, A1);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700400 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700401
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700402 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
403 assertEquals(DEVICE_UPDATED, event2.type());
404 assertDevice(DID1, SW2, event2.subject());
405 assertEquals(PID, event2.subject().providerId());
406 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
407 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700408 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700409 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700410
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700411 // no-op update from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700412 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700413 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
414
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700415 verify(clusterCommunicator);
416 assertFalse("no broadcast expected", bcast.hasCaptured());
417
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700418 // For now, Ancillary is ignored once primary appears
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700419 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700420
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700421 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
422
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700423 verify(clusterCommunicator);
424 assertFalse("no broadcast expected", bcast.hasCaptured());
425
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700426 // But, Ancillary annotations will be in effect
427 DeviceDescription description3 =
428 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700429 HW, SW1, SN, CID, A2_2);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700430 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700431
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700432 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
433 assertEquals(DEVICE_UPDATED, event3.type());
434 // basic information will be the one from Primary
435 assertDevice(DID1, SW2, event3.subject());
436 assertEquals(PID, event3.subject().providerId());
437 // but annotation from Ancillary will be merged
438 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
439 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700440 verify(clusterCommunicator);
441 // note: only annotation from PIDA is sent over the wire
442 assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700443 asList(union(A2, A2_2)), message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700444
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700445 }
446
447
448 @Test
449 public final void testMarkOffline() {
450
451 putDevice(DID1, SW1);
452 assertTrue(deviceStore.isAvailable(DID1));
453
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700454 Capture<InternalDeviceEvent> message = new Capture<>();
455 Capture<MessageSubject> subject = new Capture<>();
456 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700457
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700458 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700459 DeviceEvent event = deviceStore.markOffline(DID1);
460 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
461 assertDevice(DID1, SW1, event.subject());
462 assertFalse(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700463 verify(clusterCommunicator);
464 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700465 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700466
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700467
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700468 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700469 DeviceEvent event2 = deviceStore.markOffline(DID1);
470 assertNull("No change, no event", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700471 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700472 assertFalse(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700473 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700474
475 @Test
476 public final void testUpdatePorts() {
477 putDevice(DID1, SW1);
478 List<PortDescription> pds = Arrays.<PortDescription>asList(
479 new DefaultPortDescription(P1, true),
480 new DefaultPortDescription(P2, true)
481 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700482 Capture<InternalDeviceEvent> message = new Capture<>();
483 Capture<MessageSubject> subject = new Capture<>();
484 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700485
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700486 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700487 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700488 verify(clusterCommunicator);
489 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700490 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700491
492 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
493 for (DeviceEvent event : events) {
494 assertEquals(PORT_ADDED, event.type());
495 assertDevice(DID1, SW1, event.subject());
496 assertTrue("PortNumber is one of expected",
497 expectedPorts.remove(event.port().number()));
498 assertTrue("Port is enabled", event.port().isEnabled());
499 }
500 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
501
502
503 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
504 new DefaultPortDescription(P1, false),
505 new DefaultPortDescription(P2, true),
506 new DefaultPortDescription(P3, true)
507 );
508
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700509 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700510 events = deviceStore.updatePorts(PID, DID1, pds2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700511 verify(clusterCommunicator);
512 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700513 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700514
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700515 assertFalse("event should be triggered", events.isEmpty());
516 for (DeviceEvent event : events) {
517 PortNumber num = event.port().number();
518 if (P1.equals(num)) {
519 assertEquals(PORT_UPDATED, event.type());
520 assertDevice(DID1, SW1, event.subject());
521 assertFalse("Port is disabled", event.port().isEnabled());
522 } else if (P2.equals(num)) {
523 fail("P2 event not expected.");
524 } else if (P3.equals(num)) {
525 assertEquals(PORT_ADDED, event.type());
526 assertDevice(DID1, SW1, event.subject());
527 assertTrue("Port is enabled", event.port().isEnabled());
528 } else {
529 fail("Unknown port number encountered: " + num);
530 }
531 }
532
533 List<PortDescription> pds3 = Arrays.<PortDescription>asList(
534 new DefaultPortDescription(P1, false),
535 new DefaultPortDescription(P2, true)
536 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700537 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700538 events = deviceStore.updatePorts(PID, DID1, pds3);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700539 verify(clusterCommunicator);
540 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700541 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700542
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700543 assertFalse("event should be triggered", events.isEmpty());
544 for (DeviceEvent event : events) {
545 PortNumber num = event.port().number();
546 if (P1.equals(num)) {
547 fail("P1 event not expected.");
548 } else if (P2.equals(num)) {
549 fail("P2 event not expected.");
550 } else if (P3.equals(num)) {
551 assertEquals(PORT_REMOVED, event.type());
552 assertDevice(DID1, SW1, event.subject());
553 assertTrue("Port was enabled", event.port().isEnabled());
554 } else {
555 fail("Unknown port number encountered: " + num);
556 }
557 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700558 }
559
560 @Test
561 public final void testUpdatePortStatus() {
562 putDevice(DID1, SW1);
563 List<PortDescription> pds = Arrays.<PortDescription>asList(
564 new DefaultPortDescription(P1, true)
565 );
566 deviceStore.updatePorts(PID, DID1, pds);
567
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700568 Capture<InternalPortStatusEvent> message = new Capture<>();
569 Capture<MessageSubject> subject = new Capture<>();
570 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700571
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700572 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700573 final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
574 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700575 assertEquals(PORT_UPDATED, event.type());
576 assertDevice(DID1, SW1, event.subject());
577 assertEquals(P1, event.port().number());
578 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700579 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700580 assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, message, subject, encoder);
581 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700582 }
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700583
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700584 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700585 public final void testUpdatePortStatusAncillary() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700586 putDeviceAncillary(DID1, SW1);
587 putDevice(DID1, SW1);
588 List<PortDescription> pds = Arrays.<PortDescription>asList(
589 new DefaultPortDescription(P1, true, A1)
590 );
591 deviceStore.updatePorts(PID, DID1, pds);
592
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700593 Capture<InternalPortStatusEvent> message = new Capture<>();
594 Capture<MessageSubject> subject = new Capture<>();
595 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700596
597 // update port from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700598 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
599
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700600 final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
601 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700602 assertEquals(PORT_UPDATED, event.type());
603 assertDevice(DID1, SW1, event.subject());
604 assertEquals(P1, event.port().number());
605 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
606 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700607 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700608 assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), message, subject, encoder);
609 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700610
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700611 // update port from ancillary with no attributes
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700612 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700613 final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
614 DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700615 assertNull("Ancillary is ignored if primary exists", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700616 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700617 assertFalse(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700618
619 // but, Ancillary annotation update will be notified
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700620 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700621 final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
622 DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700623 assertEquals(PORT_UPDATED, event3.type());
624 assertDevice(DID1, SW1, event3.subject());
625 assertEquals(P1, event3.port().number());
626 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
627 assertFalse("Port is disabled", event3.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700628 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700629 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), message, subject, encoder);
630 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700631
632 // port only reported from Ancillary will be notified as down
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700633 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700634 final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
635 DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700636 assertEquals(PORT_ADDED, event4.type());
637 assertDevice(DID1, SW1, event4.subject());
638 assertEquals(P2, event4.port().number());
639 assertAnnotationsEquals(event4.port().annotations());
640 assertFalse("Port is disabled if not given from primary provider",
641 event4.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700642 verify(clusterCommunicator);
643 // TODO: verify broadcast message content
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700644 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, message, subject, encoder);
645 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700646 }
647
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700648 private void assertInternalPortStatusEvent(NodeId sender,
649 DeviceId did,
650 ProviderId pid,
651 DefaultPortDescription expectedDesc,
652 List<SparseAnnotations> expectedAnnotations,
653 Capture<InternalPortStatusEvent> actualEvent,
654 Capture<MessageSubject> actualSubject,
655 Capture<Function<InternalPortStatusEvent, byte[]>> actualEncoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700656
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700657 assertTrue(actualEvent.hasCaptured());
658 assertTrue(actualSubject.hasCaptured());
659 assertTrue(actualEncoder.hasCaptured());
660
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700661 assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700662 actualSubject.getValue());
663 assertEquals(did, actualEvent.getValue().deviceId());
664 assertEquals(pid, actualEvent.getValue().providerId());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700665 assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700666 actualEvent.getValue().portDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700667 }
668
669 private void assertPortDescriptionEquals(
670 PortDescription expectedDesc,
671 List<SparseAnnotations> expectedAnnotations,
672 PortDescription actual) {
673
674 assertEquals(expectedDesc.portNumber(), actual.portNumber());
675 assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
676
677 assertAnnotationsEquals(actual.annotations(),
678 expectedAnnotations.toArray(new SparseAnnotations[0]));
679 }
680
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700681 private <T> void resetCommunicatorExpectingNoBroadcast(
682 Capture<T> message,
683 Capture<MessageSubject> subject,
684 Capture<Function<T, byte[]>> encoder) {
685 message.reset();
686 subject.reset();
687 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700688 reset(clusterCommunicator);
689 replay(clusterCommunicator);
690 }
691
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700692 private <T> void resetCommunicatorExpectingSingleBroadcast(
693 Capture<T> message,
694 Capture<MessageSubject> subject,
695 Capture<Function<T, byte[]>> encoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700696
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700697 message.reset();
698 subject.reset();
699 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700700 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700701 clusterCommunicator.broadcast(
702 capture(message),
703 capture(subject),
704 capture(encoder));
705 expectLastCall().once();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700706 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700707 }
708
709 @Test
710 public final void testGetPorts() {
711 putDevice(DID1, SW1);
712 putDevice(DID2, SW1);
713 List<PortDescription> pds = Arrays.<PortDescription>asList(
714 new DefaultPortDescription(P1, true),
715 new DefaultPortDescription(P2, true)
716 );
717 deviceStore.updatePorts(PID, DID1, pds);
718
719 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
720 List<Port> ports = deviceStore.getPorts(DID1);
721 for (Port port : ports) {
722 assertTrue("Port is enabled", port.isEnabled());
723 assertTrue("PortNumber is one of expected",
724 expectedPorts.remove(port.number()));
725 }
726 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
727
728
729 assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
730 }
731
732 @Test
733 public final void testGetPort() {
734 putDevice(DID1, SW1);
735 putDevice(DID2, SW1);
736 List<PortDescription> pds = Arrays.<PortDescription>asList(
737 new DefaultPortDescription(P1, true),
738 new DefaultPortDescription(P2, false)
739 );
740 deviceStore.updatePorts(PID, DID1, pds);
741
742 Port port1 = deviceStore.getPort(DID1, P1);
743 assertEquals(P1, port1.number());
744 assertTrue("Port is enabled", port1.isEnabled());
745
746 Port port2 = deviceStore.getPort(DID1, P2);
747 assertEquals(P2, port2.number());
748 assertFalse("Port is disabled", port2.isEnabled());
749
750 Port port3 = deviceStore.getPort(DID1, P3);
751 assertNull("P3 not expected", port3);
752 }
753
754 @Test
755 public final void testRemoveDevice() {
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700756 putDevice(DID1, SW1, A1);
757 List<PortDescription> pds = Arrays.<PortDescription>asList(
758 new DefaultPortDescription(P1, true, A2)
759 );
760 deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700761 putDevice(DID2, SW1);
762
763 assertEquals(2, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700764 assertEquals(1, deviceStore.getPorts(DID1).size());
765 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
766 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700767
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700768 Capture<InternalDeviceEvent> message = new Capture<>();
769 Capture<MessageSubject> subject = new Capture<>();
770 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700771
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700772 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700773
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700774 DeviceEvent event = deviceStore.removeDevice(DID1);
775 assertEquals(DEVICE_REMOVED, event.type());
776 assertDevice(DID1, SW1, event.subject());
777
778 assertEquals(1, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700779 assertEquals(0, deviceStore.getPorts(DID1).size());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700780 verify(clusterCommunicator);
781 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700782 assertTrue(message.hasCaptured());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700783
784 // putBack Device, Port w/o annotation
785 putDevice(DID1, SW1);
786 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
787 new DefaultPortDescription(P1, true)
788 );
789 deviceStore.updatePorts(PID, DID1, pds2);
790
791 // annotations should not survive
792 assertEquals(2, deviceStore.getDeviceCount());
793 assertEquals(1, deviceStore.getPorts(DID1).size());
794 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations());
795 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700796 }
797
798 // If Delegates should be called only on remote events,
799 // then Simple* should never call them, thus not test required.
800 // TODO add test for Port events when we have them
801 @Ignore("Ignore until Delegate spec. is clear.")
802 @Test
803 public final void testEvents() throws InterruptedException {
804 final CountDownLatch addLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700805 DeviceStoreDelegate checkAdd = event -> {
806 assertEquals(DEVICE_ADDED, event.type());
807 assertDevice(DID1, SW1, event.subject());
808 addLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700809 };
810 final CountDownLatch updateLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700811 DeviceStoreDelegate checkUpdate = event -> {
812 assertEquals(DEVICE_UPDATED, event.type());
813 assertDevice(DID1, SW2, event.subject());
814 updateLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700815 };
816 final CountDownLatch removeLatch = new CountDownLatch(1);
Sho SHIMIZU74626412015-09-11 11:46:27 -0700817 DeviceStoreDelegate checkRemove = event -> {
818 assertEquals(DEVICE_REMOVED, event.type());
819 assertDevice(DID1, SW2, event.subject());
820 removeLatch.countDown();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700821 };
822
823 DeviceDescription description =
824 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700825 HW, SW1, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700826 deviceStore.setDelegate(checkAdd);
827 deviceStore.createOrUpdateDevice(PID, DID1, description);
828 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
829
830
831 DeviceDescription description2 =
832 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700833 HW, SW2, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700834 deviceStore.unsetDelegate(checkAdd);
835 deviceStore.setDelegate(checkUpdate);
836 deviceStore.createOrUpdateDevice(PID, DID1, description2);
837 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
838
839 deviceStore.unsetDelegate(checkUpdate);
840 deviceStore.setDelegate(checkRemove);
841 deviceStore.removeDevice(DID1);
842 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
843 }
844
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700845 private final class TestMastershipService extends MastershipServiceAdapter {
846 @Override
847 public NodeId getMasterFor(DeviceId deviceId) {
848 return NID1;
849 }
Madan Jampanic6e574f2015-05-29 13:41:52 -0700850 @Override
851 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
852 return CompletableFuture.completedFuture(null);
853 }
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700854 }
855
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700856 private static final class TestGossipDeviceStore extends GossipDeviceStore {
857
Madan Jampani53e44e62014-10-07 12:39:51 -0700858 public TestGossipDeviceStore(
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700859 DeviceClockService deviceClockService,
Madan Jampani53e44e62014-10-07 12:39:51 -0700860 ClusterService clusterService,
861 ClusterCommunicationService clusterCommunicator) {
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700862 this.deviceClockService = deviceClockService;
Madan Jampani53e44e62014-10-07 12:39:51 -0700863 this.clusterService = clusterService;
Madan Jampani47c93732014-10-06 20:46:08 -0700864 this.clusterCommunicator = clusterCommunicator;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700865 }
Madan Jampani47c93732014-10-06 20:46:08 -0700866 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700867
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800868 private static final class TestClusterService extends StaticClusterService {
Madan Jampani53e44e62014-10-07 12:39:51 -0700869
870 public TestClusterService() {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800871 localNode = ONOS1;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700872 nodes.put(NID1, ONOS1);
873 nodeStates.put(NID1, ACTIVE);
874
875 nodes.put(NID2, ONOS2);
876 nodeStates.put(NID2, ACTIVE);
Madan Jampani53e44e62014-10-07 12:39:51 -0700877 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700878 }
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700879
Madan Jampani565a66a2015-07-25 17:01:13 -0700880 private final class TestDeviceClockService extends DeviceClockServiceAdapter {
881
882 private final AtomicLong ticker = new AtomicLong();
883
884 @Override
885 public Timestamp getTimestamp(DeviceId deviceId) {
886 if (DID1.equals(deviceId)) {
887 return new MastershipBasedTimestamp(1, ticker.getAndIncrement());
888 } else if (DID2.equals(deviceId)) {
889 return new MastershipBasedTimestamp(2, ticker.getAndIncrement());
890 } else {
891 throw new IllegalStateException();
892 }
893 }
894
895 @Override
896 public boolean isTimestampAvailable(DeviceId deviceId) {
897 return DID1.equals(deviceId) || DID2.equals(deviceId);
898 }
899 }
900
Thomas Vachuskafdbc4c22015-05-29 15:53:01 -0700901 private class TestDatabaseManager extends DatabaseManager {
902 void init(ClusterService clusterService,
903 ClusterCommunicationService clusterCommunicator) {
904 this.clusterService = clusterService;
905 this.clusterCommunicator = clusterCommunicator;
906 }
907 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700908}