blob: f271de4645f07f71a042b4014bd8253cd38a66d6 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
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;
35import org.onosproject.mastership.MastershipTerm;
36import org.onosproject.net.Annotations;
37import org.onosproject.net.DefaultAnnotations;
38import org.onosproject.net.Device;
39import org.onosproject.net.DeviceId;
40import 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;
46import org.onosproject.net.device.DeviceDescription;
47import org.onosproject.net.device.DeviceEvent;
48import org.onosproject.net.device.DeviceStore;
49import org.onosproject.net.device.DeviceStoreDelegate;
50import org.onosproject.net.device.PortDescription;
51import org.onosproject.net.provider.ProviderId;
52import org.onosproject.store.cluster.StaticClusterService;
53import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
54import org.onosproject.store.cluster.messaging.ClusterMessage;
55import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
56import org.onosproject.store.cluster.messaging.MessageSubject;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070057
Jonathan Hart7d656f42015-01-27 14:07:23 -080058import java.io.IOException;
59import java.util.Arrays;
60import java.util.Collections;
61import java.util.HashMap;
62import java.util.List;
63import java.util.Map;
64import java.util.Set;
65import java.util.concurrent.CountDownLatch;
Madan Jampani2af244a2015-02-22 13:12:01 -080066import java.util.concurrent.ExecutorService;
Jonathan Hart7d656f42015-01-27 14:07:23 -080067import java.util.concurrent.TimeUnit;
Madan Jampani2bfa94c2015-04-11 05:03:49 -070068import java.util.function.Function;
Jonathan Hart7d656f42015-01-27 14:07:23 -080069
70import static java.util.Arrays.asList;
71import static org.easymock.EasyMock.*;
72import static org.junit.Assert.*;
73import static org.onosproject.cluster.ControllerNode.State.ACTIVE;
74import static org.onosproject.net.DefaultAnnotations.union;
75import static org.onosproject.net.Device.Type.SWITCH;
76import static org.onosproject.net.DeviceId.deviceId;
77import static org.onosproject.net.device.DeviceEvent.Type.*;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070078
79
80// TODO add tests for remote replication
81/**
82 * Test of the gossip based distributed DeviceStore implementation.
83 */
84public class GossipDeviceStoreTest {
85
86 private static final ProviderId PID = new ProviderId("of", "foo");
87 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
88 private static final DeviceId DID1 = deviceId("of:foo");
89 private static final DeviceId DID2 = deviceId("of:bar");
90 private static final String MFR = "whitebox";
91 private static final String HW = "1.1.x";
92 private static final String SW1 = "3.8.1";
93 private static final String SW2 = "3.9.5";
94 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -070095 private static final ChassisId CID = new ChassisId();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -070096
97 private static final PortNumber P1 = PortNumber.portNumber(1);
98 private static final PortNumber P2 = PortNumber.portNumber(2);
99 private static final PortNumber P3 = PortNumber.portNumber(3);
100
101 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
102 .set("A1", "a1")
103 .set("B1", "b1")
104 .build();
105 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
106 .remove("A1")
107 .set("B3", "b3")
108 .build();
109 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
110 .set("A2", "a2")
111 .set("B2", "b2")
112 .build();
113 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
114 .remove("A2")
115 .set("B4", "b4")
116 .build();
117
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700118 // local node
119 private static final NodeId NID1 = new NodeId("local");
120 private static final ControllerNode ONOS1 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700121 new DefaultControllerNode(NID1, IpAddress.valueOf("127.0.0.1"));
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700122
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700123 // remote node
124 private static final NodeId NID2 = new NodeId("remote");
125 private static final ControllerNode ONOS2 =
Pavlin Radoslavov444b5192014-10-28 10:45:19 -0700126 new DefaultControllerNode(NID2, IpAddress.valueOf("127.0.0.2"));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700127 private static final List<SparseAnnotations> NO_ANNOTATION = Collections.<SparseAnnotations>emptyList();
128
129
130 private TestGossipDeviceStore testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700131 private GossipDeviceStore gossipDeviceStore;
132 private DeviceStore deviceStore;
133
134 private DeviceClockManager deviceClockManager;
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700135 private DeviceClockService deviceClockService;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700136 private ClusterCommunicationService clusterCommunicator;
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800137
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700138 @BeforeClass
139 public static void setUpBeforeClass() throws Exception {
140 }
141
142 @AfterClass
143 public static void tearDownAfterClass() throws Exception {
144 }
145
146
147 @Before
148 public void setUp() throws Exception {
149 deviceClockManager = new DeviceClockManager();
150 deviceClockManager.activate();
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700151 deviceClockService = deviceClockManager;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700152
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700153 deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1));
154 deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2));
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700155
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700156 clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
157 clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
Madan Jampani2af244a2015-02-22 13:12:01 -0800158 anyObject(ClusterMessageHandler.class), anyObject(ExecutorService.class));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700159 expectLastCall().anyTimes();
160 replay(clusterCommunicator);
Madan Jampani53e44e62014-10-07 12:39:51 -0700161 ClusterService clusterService = new TestClusterService();
Madan Jampani47c93732014-10-06 20:46:08 -0700162
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700163 testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700164 testGossipDeviceStore.mastershipService = new TestMastershipService();
165
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700166 gossipDeviceStore = testGossipDeviceStore;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700167 gossipDeviceStore.activate();
168 deviceStore = gossipDeviceStore;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700169 verify(clusterCommunicator);
170 reset(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700171 }
172
173 @After
174 public void tearDown() throws Exception {
175 gossipDeviceStore.deactivate();
176 deviceClockManager.deactivate();
177 }
178
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700179 private void putDevice(DeviceId deviceId, String swVersion,
180 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700181 DeviceDescription description =
182 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700183 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700184 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700185 clusterCommunicator.<InternalDeviceEvent>broadcast(
186 anyObject(InternalDeviceEvent.class), anyObject(MessageSubject.class), anyObject(Function.class));
187 expectLastCall().anyTimes();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700188 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700189 deviceStore.createOrUpdateDevice(PID, deviceId, description);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700190 verify(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700191 }
192
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700193 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
194 SparseAnnotations... annotations) {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700195 DeviceDescription description =
196 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700197 HW, swVersion, SN, CID, annotations);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700198 deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
199 }
200
201 private static void assertDevice(DeviceId id, String swVersion, Device device) {
202 assertNotNull(device);
203 assertEquals(id, device.id());
204 assertEquals(MFR, device.manufacturer());
205 assertEquals(HW, device.hwVersion());
206 assertEquals(swVersion, device.swVersion());
207 assertEquals(SN, device.serialNumber());
208 }
209
210 /**
211 * Verifies that Annotations created by merging {@code annotations} is
212 * equal to actual Annotations.
213 *
214 * @param actual Annotations to check
215 * @param annotations
216 */
217 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700218 SparseAnnotations expected = DefaultAnnotations.builder().build();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700219 for (SparseAnnotations a : annotations) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700220 expected = DefaultAnnotations.union(expected, a);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700221 }
222 assertEquals(expected.keys(), actual.keys());
223 for (String key : expected.keys()) {
224 assertEquals(expected.value(key), actual.value(key));
225 }
226 }
227
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700228 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
229 DeviceDescription actual) {
230 if (expected == actual) {
231 return;
232 }
233 assertEquals(expected.deviceURI(), actual.deviceURI());
234 assertEquals(expected.hwVersion(), actual.hwVersion());
235 assertEquals(expected.manufacturer(), actual.manufacturer());
236 assertEquals(expected.serialNumber(), actual.serialNumber());
237 assertEquals(expected.swVersion(), actual.swVersion());
238
239 assertAnnotationsEquals(actual.annotations(), expected.annotations());
240 }
241
242 private static void assertDeviceDescriptionEquals(DeviceDescription expected,
243 List<SparseAnnotations> expectedAnnotations,
244 DeviceDescription actual) {
245 if (expected == actual) {
246 return;
247 }
248 assertEquals(expected.deviceURI(), actual.deviceURI());
249 assertEquals(expected.hwVersion(), actual.hwVersion());
250 assertEquals(expected.manufacturer(), actual.manufacturer());
251 assertEquals(expected.serialNumber(), actual.serialNumber());
252 assertEquals(expected.swVersion(), actual.swVersion());
253
254 assertAnnotationsEquals(actual.annotations(),
255 expectedAnnotations.toArray(new SparseAnnotations[0]));
256 }
257
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700258 @Test
259 public final void testGetDeviceCount() {
260 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
261
262 putDevice(DID1, SW1);
263 putDevice(DID2, SW2);
264 putDevice(DID1, SW1);
265
266 assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
267 }
268
269 @Test
270 public final void testGetDevices() {
271 assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
272
273 putDevice(DID1, SW1);
274 putDevice(DID2, SW2);
275 putDevice(DID1, SW1);
276
277 assertEquals("expect 2 uniq devices",
278 2, Iterables.size(deviceStore.getDevices()));
279
280 Map<DeviceId, Device> devices = new HashMap<>();
281 for (Device device : deviceStore.getDevices()) {
282 devices.put(device.id(), device);
283 }
284
285 assertDevice(DID1, SW1, devices.get(DID1));
286 assertDevice(DID2, SW2, devices.get(DID2));
287
288 // add case for new node?
289 }
290
291 @Test
292 public final void testGetDevice() {
293
294 putDevice(DID1, SW1);
295
296 assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
297 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
298 }
299
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700300 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700301 DeviceId deviceId,
302 ProviderId providerId,
303 DeviceDescription expectedDesc,
304 Capture<InternalDeviceEvent> actualEvent,
305 Capture<MessageSubject> actualSubject,
306 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
307 assertTrue(actualEvent.hasCaptured());
308 assertTrue(actualSubject.hasCaptured());
309 assertTrue(actualEncoder.hasCaptured());
310
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700311 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700312 actualSubject.getValue());
313 assertEquals(deviceId, actualEvent.getValue().deviceId());
314 assertEquals(providerId, actualEvent.getValue().providerId());
315 assertDeviceDescriptionEquals(expectedDesc, actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700316 }
317
318 private void assertInternalDeviceEvent(NodeId sender,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700319 DeviceId deviceId,
320 ProviderId providerId,
321 DeviceDescription expectedDesc,
322 List<SparseAnnotations> expectedAnnotations,
323 Capture<InternalDeviceEvent> actualEvent,
324 Capture<MessageSubject> actualSubject,
325 Capture<Function<InternalDeviceEvent, byte[]>> actualEncoder) {
326 assertTrue(actualEvent.hasCaptured());
327 assertTrue(actualSubject.hasCaptured());
328 assertTrue(actualEncoder.hasCaptured());
329
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700330 assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700331 actualSubject.getValue());
332 assertEquals(deviceId, actualEvent.getValue().deviceId());
333 assertEquals(providerId, actualEvent.getValue().providerId());
334 assertDeviceDescriptionEquals(
335 expectedDesc,
336 expectedAnnotations,
337 actualEvent.getValue().deviceDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700338 }
339
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700340 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700341 public final void testCreateOrUpdateDevice() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700342 DeviceDescription description =
343 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700344 HW, SW1, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700345 Capture<InternalDeviceEvent> message = new Capture<>();
346 Capture<MessageSubject> subject = new Capture<>();
347 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700348
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700349 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700350 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
351 assertEquals(DEVICE_ADDED, event.type());
352 assertDevice(DID1, SW1, event.subject());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700353 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700354 assertInternalDeviceEvent(NID1, DID1, PID, description, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700355
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700356
357 DeviceDescription description2 =
358 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700359 HW, SW2, SN, CID);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700360 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700361 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
362 assertEquals(DEVICE_UPDATED, event2.type());
363 assertDevice(DID1, SW2, event2.subject());
364
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700365 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700366 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700367 reset(clusterCommunicator);
368
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700369 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
370 }
371
372 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700373 public final void testCreateOrUpdateDeviceAncillary() throws IOException {
374 // add
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700375 DeviceDescription description =
376 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700377 HW, SW1, SN, CID, A2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700378 Capture<ClusterMessage> bcast = new Capture<>();
379
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700380 Capture<InternalDeviceEvent> message = new Capture<>();
381 Capture<MessageSubject> subject = new Capture<>();
382 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
383
384 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700385 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
386 assertEquals(DEVICE_ADDED, event.type());
387 assertDevice(DID1, SW1, event.subject());
388 assertEquals(PIDA, event.subject().providerId());
389 assertAnnotationsEquals(event.subject().annotations(), A2);
390 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700391 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700392 assertInternalDeviceEvent(NID1, DID1, PIDA, description, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700393
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700394 // update from primary
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700395 DeviceDescription description2 =
396 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700397 HW, SW2, SN, CID, A1);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700398 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700399
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700400 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
401 assertEquals(DEVICE_UPDATED, event2.type());
402 assertDevice(DID1, SW2, event2.subject());
403 assertEquals(PID, event2.subject().providerId());
404 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
405 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700406 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700407 assertInternalDeviceEvent(NID1, DID1, PID, description2, message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700408
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700409 // no-op update from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700410 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700411 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
412
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700413 verify(clusterCommunicator);
414 assertFalse("no broadcast expected", bcast.hasCaptured());
415
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700416 // For now, Ancillary is ignored once primary appears
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700417 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700418
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700419 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
420
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700421 verify(clusterCommunicator);
422 assertFalse("no broadcast expected", bcast.hasCaptured());
423
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700424 // But, Ancillary annotations will be in effect
425 DeviceDescription description3 =
426 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700427 HW, SW1, SN, CID, A2_2);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700428 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700429
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700430 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
431 assertEquals(DEVICE_UPDATED, event3.type());
432 // basic information will be the one from Primary
433 assertDevice(DID1, SW2, event3.subject());
434 assertEquals(PID, event3.subject().providerId());
435 // but annotation from Ancillary will be merged
436 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
437 assertTrue(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700438 verify(clusterCommunicator);
439 // note: only annotation from PIDA is sent over the wire
440 assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700441 asList(union(A2, A2_2)), message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700442
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700443 }
444
445
446 @Test
447 public final void testMarkOffline() {
448
449 putDevice(DID1, SW1);
450 assertTrue(deviceStore.isAvailable(DID1));
451
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700452 Capture<InternalDeviceEvent> message = new Capture<>();
453 Capture<MessageSubject> subject = new Capture<>();
454 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700455
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700456 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700457 DeviceEvent event = deviceStore.markOffline(DID1);
458 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
459 assertDevice(DID1, SW1, event.subject());
460 assertFalse(deviceStore.isAvailable(DID1));
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700461 verify(clusterCommunicator);
462 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700463 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700464
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700465
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700466 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700467 DeviceEvent event2 = deviceStore.markOffline(DID1);
468 assertNull("No change, no event", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700469 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700470 assertFalse(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700471 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700472
473 @Test
474 public final void testUpdatePorts() {
475 putDevice(DID1, SW1);
476 List<PortDescription> pds = Arrays.<PortDescription>asList(
477 new DefaultPortDescription(P1, true),
478 new DefaultPortDescription(P2, true)
479 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700480 Capture<InternalDeviceEvent> message = new Capture<>();
481 Capture<MessageSubject> subject = new Capture<>();
482 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700483
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700484 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700485 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700486 verify(clusterCommunicator);
487 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700488 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700489
490 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
491 for (DeviceEvent event : events) {
492 assertEquals(PORT_ADDED, event.type());
493 assertDevice(DID1, SW1, event.subject());
494 assertTrue("PortNumber is one of expected",
495 expectedPorts.remove(event.port().number()));
496 assertTrue("Port is enabled", event.port().isEnabled());
497 }
498 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
499
500
501 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
502 new DefaultPortDescription(P1, false),
503 new DefaultPortDescription(P2, true),
504 new DefaultPortDescription(P3, true)
505 );
506
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700507 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700508 events = deviceStore.updatePorts(PID, DID1, pds2);
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 HIGUCHI47c40882014-10-10 18:44:37 -0700512
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700513 assertFalse("event should be triggered", events.isEmpty());
514 for (DeviceEvent event : events) {
515 PortNumber num = event.port().number();
516 if (P1.equals(num)) {
517 assertEquals(PORT_UPDATED, event.type());
518 assertDevice(DID1, SW1, event.subject());
519 assertFalse("Port is disabled", event.port().isEnabled());
520 } else if (P2.equals(num)) {
521 fail("P2 event not expected.");
522 } else if (P3.equals(num)) {
523 assertEquals(PORT_ADDED, event.type());
524 assertDevice(DID1, SW1, event.subject());
525 assertTrue("Port is enabled", event.port().isEnabled());
526 } else {
527 fail("Unknown port number encountered: " + num);
528 }
529 }
530
531 List<PortDescription> pds3 = Arrays.<PortDescription>asList(
532 new DefaultPortDescription(P1, false),
533 new DefaultPortDescription(P2, true)
534 );
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700535 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700536 events = deviceStore.updatePorts(PID, DID1, pds3);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700537 verify(clusterCommunicator);
538 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700539 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700540
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700541 assertFalse("event should be triggered", events.isEmpty());
542 for (DeviceEvent event : events) {
543 PortNumber num = event.port().number();
544 if (P1.equals(num)) {
545 fail("P1 event not expected.");
546 } else if (P2.equals(num)) {
547 fail("P2 event not expected.");
548 } else if (P3.equals(num)) {
549 assertEquals(PORT_REMOVED, event.type());
550 assertDevice(DID1, SW1, event.subject());
551 assertTrue("Port was enabled", event.port().isEnabled());
552 } else {
553 fail("Unknown port number encountered: " + num);
554 }
555 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700556 }
557
558 @Test
559 public final void testUpdatePortStatus() {
560 putDevice(DID1, SW1);
561 List<PortDescription> pds = Arrays.<PortDescription>asList(
562 new DefaultPortDescription(P1, true)
563 );
564 deviceStore.updatePorts(PID, DID1, pds);
565
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700566 Capture<InternalPortStatusEvent> message = new Capture<>();
567 Capture<MessageSubject> subject = new Capture<>();
568 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700569
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700570 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700571 final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
572 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700573 assertEquals(PORT_UPDATED, event.type());
574 assertDevice(DID1, SW1, event.subject());
575 assertEquals(P1, event.port().number());
576 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700577 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700578 assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, message, subject, encoder);
579 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700580 }
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700581
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700582 @Test
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700583 public final void testUpdatePortStatusAncillary() throws IOException {
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700584 putDeviceAncillary(DID1, SW1);
585 putDevice(DID1, SW1);
586 List<PortDescription> pds = Arrays.<PortDescription>asList(
587 new DefaultPortDescription(P1, true, A1)
588 );
589 deviceStore.updatePorts(PID, DID1, pds);
590
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700591 Capture<InternalPortStatusEvent> message = new Capture<>();
592 Capture<MessageSubject> subject = new Capture<>();
593 Capture<Function<InternalPortStatusEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700594
595 // update port from primary
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700596 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
597
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700598 final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
599 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700600 assertEquals(PORT_UPDATED, event.type());
601 assertDevice(DID1, SW1, event.subject());
602 assertEquals(P1, event.port().number());
603 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
604 assertFalse("Port is disabled", event.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700605 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700606 assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), message, subject, encoder);
607 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700608
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700609 // update port from ancillary with no attributes
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700610 resetCommunicatorExpectingNoBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700611 final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
612 DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700613 assertNull("Ancillary is ignored if primary exists", event2);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700614 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700615 assertFalse(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700616
617 // but, Ancillary annotation update will be notified
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700618 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700619 final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
620 DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700621 assertEquals(PORT_UPDATED, event3.type());
622 assertDevice(DID1, SW1, event3.subject());
623 assertEquals(P1, event3.port().number());
624 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
625 assertFalse("Port is disabled", event3.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700626 verify(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700627 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), message, subject, encoder);
628 assertTrue(message.hasCaptured());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700629
630 // port only reported from Ancillary will be notified as down
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700631 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700632 final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
633 DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700634 assertEquals(PORT_ADDED, event4.type());
635 assertDevice(DID1, SW1, event4.subject());
636 assertEquals(P2, event4.port().number());
637 assertAnnotationsEquals(event4.port().annotations());
638 assertFalse("Port is disabled if not given from primary provider",
639 event4.port().isEnabled());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700640 verify(clusterCommunicator);
641 // TODO: verify broadcast message content
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700642 assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, message, subject, encoder);
643 assertTrue(message.hasCaptured());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700644 }
645
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700646 private void assertInternalPortStatusEvent(NodeId sender,
647 DeviceId did,
648 ProviderId pid,
649 DefaultPortDescription expectedDesc,
650 List<SparseAnnotations> expectedAnnotations,
651 Capture<InternalPortStatusEvent> actualEvent,
652 Capture<MessageSubject> actualSubject,
653 Capture<Function<InternalPortStatusEvent, byte[]>> actualEncoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700654
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700655 assertTrue(actualEvent.hasCaptured());
656 assertTrue(actualSubject.hasCaptured());
657 assertTrue(actualEncoder.hasCaptured());
658
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700659 assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700660 actualSubject.getValue());
661 assertEquals(did, actualEvent.getValue().deviceId());
662 assertEquals(pid, actualEvent.getValue().providerId());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700663 assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700664 actualEvent.getValue().portDescription().value());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700665 }
666
667 private void assertPortDescriptionEquals(
668 PortDescription expectedDesc,
669 List<SparseAnnotations> expectedAnnotations,
670 PortDescription actual) {
671
672 assertEquals(expectedDesc.portNumber(), actual.portNumber());
673 assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
674
675 assertAnnotationsEquals(actual.annotations(),
676 expectedAnnotations.toArray(new SparseAnnotations[0]));
677 }
678
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700679 private <T> void resetCommunicatorExpectingNoBroadcast(
680 Capture<T> message,
681 Capture<MessageSubject> subject,
682 Capture<Function<T, byte[]>> encoder) {
683 message.reset();
684 subject.reset();
685 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700686 reset(clusterCommunicator);
687 replay(clusterCommunicator);
688 }
689
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700690 private <T> void resetCommunicatorExpectingSingleBroadcast(
691 Capture<T> message,
692 Capture<MessageSubject> subject,
693 Capture<Function<T, byte[]>> encoder) {
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700694
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700695 message.reset();
696 subject.reset();
697 encoder.reset();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700698 reset(clusterCommunicator);
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700699 clusterCommunicator.broadcast(
700 capture(message),
701 capture(subject),
702 capture(encoder));
703 expectLastCall().once();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700704 replay(clusterCommunicator);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700705 }
706
707 @Test
708 public final void testGetPorts() {
709 putDevice(DID1, SW1);
710 putDevice(DID2, SW1);
711 List<PortDescription> pds = Arrays.<PortDescription>asList(
712 new DefaultPortDescription(P1, true),
713 new DefaultPortDescription(P2, true)
714 );
715 deviceStore.updatePorts(PID, DID1, pds);
716
717 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
718 List<Port> ports = deviceStore.getPorts(DID1);
719 for (Port port : ports) {
720 assertTrue("Port is enabled", port.isEnabled());
721 assertTrue("PortNumber is one of expected",
722 expectedPorts.remove(port.number()));
723 }
724 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
725
726
727 assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
728 }
729
730 @Test
731 public final void testGetPort() {
732 putDevice(DID1, SW1);
733 putDevice(DID2, SW1);
734 List<PortDescription> pds = Arrays.<PortDescription>asList(
735 new DefaultPortDescription(P1, true),
736 new DefaultPortDescription(P2, false)
737 );
738 deviceStore.updatePorts(PID, DID1, pds);
739
740 Port port1 = deviceStore.getPort(DID1, P1);
741 assertEquals(P1, port1.number());
742 assertTrue("Port is enabled", port1.isEnabled());
743
744 Port port2 = deviceStore.getPort(DID1, P2);
745 assertEquals(P2, port2.number());
746 assertFalse("Port is disabled", port2.isEnabled());
747
748 Port port3 = deviceStore.getPort(DID1, P3);
749 assertNull("P3 not expected", port3);
750 }
751
752 @Test
753 public final void testRemoveDevice() {
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700754 putDevice(DID1, SW1, A1);
755 List<PortDescription> pds = Arrays.<PortDescription>asList(
756 new DefaultPortDescription(P1, true, A2)
757 );
758 deviceStore.updatePorts(PID, DID1, pds);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700759 putDevice(DID2, SW1);
760
761 assertEquals(2, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700762 assertEquals(1, deviceStore.getPorts(DID1).size());
763 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
764 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700765
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700766 Capture<InternalDeviceEvent> message = new Capture<>();
767 Capture<MessageSubject> subject = new Capture<>();
768 Capture<Function<InternalDeviceEvent, byte[]>> encoder = new Capture<>();
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700769
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700770 resetCommunicatorExpectingSingleBroadcast(message, subject, encoder);
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700771
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700772 DeviceEvent event = deviceStore.removeDevice(DID1);
773 assertEquals(DEVICE_REMOVED, event.type());
774 assertDevice(DID1, SW1, event.subject());
775
776 assertEquals(1, deviceStore.getDeviceCount());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700777 assertEquals(0, deviceStore.getPorts(DID1).size());
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700778 verify(clusterCommunicator);
779 // TODO: verify broadcast message
Madan Jampani2bfa94c2015-04-11 05:03:49 -0700780 assertTrue(message.hasCaptured());
Yuta HIGUCHI0d6a5e62014-10-03 15:54:09 -0700781
782 // putBack Device, Port w/o annotation
783 putDevice(DID1, SW1);
784 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
785 new DefaultPortDescription(P1, true)
786 );
787 deviceStore.updatePorts(PID, DID1, pds2);
788
789 // annotations should not survive
790 assertEquals(2, deviceStore.getDeviceCount());
791 assertEquals(1, deviceStore.getPorts(DID1).size());
792 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations());
793 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations());
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700794 }
795
796 // If Delegates should be called only on remote events,
797 // then Simple* should never call them, thus not test required.
798 // TODO add test for Port events when we have them
799 @Ignore("Ignore until Delegate spec. is clear.")
800 @Test
801 public final void testEvents() throws InterruptedException {
802 final CountDownLatch addLatch = new CountDownLatch(1);
803 DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() {
804 @Override
805 public void notify(DeviceEvent event) {
806 assertEquals(DEVICE_ADDED, event.type());
807 assertDevice(DID1, SW1, event.subject());
808 addLatch.countDown();
809 }
810 };
811 final CountDownLatch updateLatch = new CountDownLatch(1);
812 DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() {
813 @Override
814 public void notify(DeviceEvent event) {
815 assertEquals(DEVICE_UPDATED, event.type());
816 assertDevice(DID1, SW2, event.subject());
817 updateLatch.countDown();
818 }
819 };
820 final CountDownLatch removeLatch = new CountDownLatch(1);
821 DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() {
822 @Override
823 public void notify(DeviceEvent event) {
824 assertEquals(DEVICE_REMOVED, event.type());
825 assertDevice(DID1, SW2, event.subject());
826 removeLatch.countDown();
827 }
828 };
829
830 DeviceDescription description =
831 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700832 HW, SW1, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700833 deviceStore.setDelegate(checkAdd);
834 deviceStore.createOrUpdateDevice(PID, DID1, description);
835 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
836
837
838 DeviceDescription description2 =
839 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700840 HW, SW2, SN, CID);
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700841 deviceStore.unsetDelegate(checkAdd);
842 deviceStore.setDelegate(checkUpdate);
843 deviceStore.createOrUpdateDevice(PID, DID1, description2);
844 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
845
846 deviceStore.unsetDelegate(checkUpdate);
847 deviceStore.setDelegate(checkRemove);
848 deviceStore.removeDevice(DID1);
849 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
850 }
851
Yuta HIGUCHIe8252bb2014-10-22 09:41:01 -0700852 private final class TestMastershipService extends MastershipServiceAdapter {
853 @Override
854 public NodeId getMasterFor(DeviceId deviceId) {
855 return NID1;
856 }
857 }
858
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700859 private static final class TestGossipDeviceStore extends GossipDeviceStore {
860
Madan Jampani53e44e62014-10-07 12:39:51 -0700861 public TestGossipDeviceStore(
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700862 DeviceClockService deviceClockService,
Madan Jampani53e44e62014-10-07 12:39:51 -0700863 ClusterService clusterService,
864 ClusterCommunicationService clusterCommunicator) {
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700865 this.deviceClockService = deviceClockService;
Madan Jampani53e44e62014-10-07 12:39:51 -0700866 this.clusterService = clusterService;
Madan Jampani47c93732014-10-06 20:46:08 -0700867 this.clusterCommunicator = clusterCommunicator;
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700868 }
Madan Jampani47c93732014-10-06 20:46:08 -0700869 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700870
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800871 private static final class TestClusterService extends StaticClusterService {
Madan Jampani53e44e62014-10-07 12:39:51 -0700872
873 public TestClusterService() {
Yuta HIGUCHI3e5d11a2014-11-04 14:16:44 -0800874 localNode = ONOS1;
Yuta HIGUCHI47c40882014-10-10 18:44:37 -0700875 nodes.put(NID1, ONOS1);
876 nodeStates.put(NID1, ACTIVE);
877
878 nodes.put(NID2, ONOS2);
879 nodeStates.put(NID2, ACTIVE);
Madan Jampani53e44e62014-10-07 12:39:51 -0700880 }
Madan Jampani53e44e62014-10-07 12:39:51 -0700881 }
Yuta HIGUCHI67a527f2014-10-02 22:23:54 -0700882}