2 * Copyright 2014 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 package org.onosproject.store.trivial;
22 import static org.junit.Assert.*;
23 import static org.onosproject.net.Device.Type.SWITCH;
24 import static org.onosproject.net.DeviceId.deviceId;
25 import static org.onosproject.net.device.DeviceEvent.Type.*;
26 import static org.onosproject.net.NetTestTools.assertAnnotationsEquals;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.List;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.TimeUnit;
36 import org.junit.After;
37 import org.junit.AfterClass;
38 import org.junit.Before;
39 import org.junit.BeforeClass;
40 import org.junit.Ignore;
41 import org.junit.Test;
42 import org.onosproject.net.DefaultAnnotations;
43 import org.onosproject.net.Device;
44 import org.onosproject.net.DeviceId;
45 import org.onosproject.net.Port;
46 import org.onosproject.net.PortNumber;
47 import org.onosproject.net.SparseAnnotations;
48 import org.onosproject.net.device.DefaultDeviceDescription;
49 import org.onosproject.net.device.DefaultPortDescription;
50 import org.onosproject.net.device.DeviceDescription;
51 import org.onosproject.net.device.DeviceEvent;
52 import org.onosproject.net.device.DeviceStore;
53 import org.onosproject.net.device.DeviceStoreDelegate;
54 import org.onosproject.net.device.PortDescription;
55 import org.onosproject.net.provider.ProviderId;
57 import com.google.common.collect.Iterables;
58 import com.google.common.collect.Sets;
60 import org.onlab.packet.ChassisId;
63 * Test of the simple DeviceStore implementation.
65 public class SimpleDeviceStoreTest {
67 private static final ProviderId PID = new ProviderId("of", "foo");
68 private static final ProviderId PIDA = new ProviderId("of", "bar", true);
69 private static final DeviceId DID1 = deviceId("of:foo");
70 private static final DeviceId DID2 = deviceId("of:bar");
71 private static final String MFR = "whitebox";
72 private static final String HW = "1.1.x";
73 private static final String SW1 = "3.8.1";
74 private static final String SW2 = "3.9.5";
75 private static final String SN = "43311-12345";
76 private static final ChassisId CID = new ChassisId();
78 private static final PortNumber P1 = PortNumber.portNumber(1);
79 private static final PortNumber P2 = PortNumber.portNumber(2);
80 private static final PortNumber P3 = PortNumber.portNumber(3);
82 private static final SparseAnnotations A1 = DefaultAnnotations.builder()
86 private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
90 private static final SparseAnnotations A2 = DefaultAnnotations.builder()
94 private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
99 private SimpleDeviceStore simpleDeviceStore;
100 private DeviceStore deviceStore;
105 public static void setUpBeforeClass() throws Exception {
109 public static void tearDownAfterClass() throws Exception {
114 public void setUp() throws Exception {
115 simpleDeviceStore = new SimpleDeviceStore();
116 simpleDeviceStore.activate();
117 deviceStore = simpleDeviceStore;
121 public void tearDown() throws Exception {
122 simpleDeviceStore.deactivate();
125 private void putDevice(DeviceId deviceId, String swVersion,
126 SparseAnnotations... annotations) {
127 DeviceDescription description =
128 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
129 HW, swVersion, SN, CID, annotations);
130 deviceStore.createOrUpdateDevice(PID, deviceId, description);
133 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
134 SparseAnnotations... annotations) {
135 DeviceDescription description =
136 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
137 HW, swVersion, SN, CID, annotations);
138 deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
141 private static void assertDevice(DeviceId id, String swVersion, Device device) {
142 assertNotNull(device);
143 assertEquals(id, device.id());
144 assertEquals(MFR, device.manufacturer());
145 assertEquals(HW, device.hwVersion());
146 assertEquals(swVersion, device.swVersion());
147 assertEquals(SN, device.serialNumber());
151 public final void testGetDeviceCount() {
152 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
154 putDevice(DID1, SW1);
155 putDevice(DID2, SW2);
156 putDevice(DID1, SW1);
158 assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
162 public final void testGetDevices() {
163 assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
165 putDevice(DID1, SW1);
166 putDevice(DID2, SW2);
167 putDevice(DID1, SW1);
169 assertEquals("expect 2 uniq devices",
170 2, Iterables.size(deviceStore.getDevices()));
172 Map<DeviceId, Device> devices = new HashMap<>();
173 for (Device device : deviceStore.getDevices()) {
174 devices.put(device.id(), device);
177 assertDevice(DID1, SW1, devices.get(DID1));
178 assertDevice(DID2, SW2, devices.get(DID2));
180 // add case for new node?
184 public final void testGetDevice() {
186 putDevice(DID1, SW1);
188 assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
189 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
193 public final void testCreateOrUpdateDevice() {
194 DeviceDescription description =
195 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
197 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
198 assertEquals(DEVICE_ADDED, event.type());
199 assertDevice(DID1, SW1, event.subject());
201 DeviceDescription description2 =
202 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
204 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
205 assertEquals(DEVICE_UPDATED, event2.type());
206 assertDevice(DID1, SW2, event2.subject());
208 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
212 public final void testCreateOrUpdateDeviceAncillary() {
213 DeviceDescription description =
214 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
215 HW, SW1, SN, CID, A2);
216 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
217 assertEquals(DEVICE_ADDED, event.type());
218 assertDevice(DID1, SW1, event.subject());
219 assertEquals(PIDA, event.subject().providerId());
220 assertAnnotationsEquals(event.subject().annotations(), A2);
221 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
223 DeviceDescription description2 =
224 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
225 HW, SW2, SN, CID, A1);
226 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
227 assertEquals(DEVICE_UPDATED, event2.type());
228 assertDevice(DID1, SW2, event2.subject());
229 assertEquals(PID, event2.subject().providerId());
230 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
231 assertTrue(deviceStore.isAvailable(DID1));
233 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
235 // For now, Ancillary is ignored once primary appears
236 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
238 // But, Ancillary annotations will be in effect
239 DeviceDescription description3 =
240 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
241 HW, SW1, SN, CID, A2_2);
242 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
243 assertEquals(DEVICE_UPDATED, event3.type());
244 // basic information will be the one from Primary
245 assertDevice(DID1, SW2, event3.subject());
246 assertEquals(PID, event3.subject().providerId());
247 // but annotation from Ancillary will be merged
248 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
249 assertTrue(deviceStore.isAvailable(DID1));
254 public final void testMarkOffline() {
256 putDevice(DID1, SW1);
257 assertTrue(deviceStore.isAvailable(DID1));
259 DeviceEvent event = deviceStore.markOffline(DID1);
260 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
261 assertDevice(DID1, SW1, event.subject());
262 assertFalse(deviceStore.isAvailable(DID1));
264 DeviceEvent event2 = deviceStore.markOffline(DID1);
265 assertNull("No change, no event", event2);
269 public final void testUpdatePorts() {
270 putDevice(DID1, SW1);
271 List<PortDescription> pds = Arrays.<PortDescription>asList(
272 new DefaultPortDescription(P1, true),
273 new DefaultPortDescription(P2, true)
276 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
278 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
279 for (DeviceEvent event : events) {
280 assertEquals(PORT_ADDED, event.type());
281 assertDevice(DID1, SW1, event.subject());
282 assertTrue("PortNumber is one of expected",
283 expectedPorts.remove(event.port().number()));
284 assertTrue("Port is enabled", event.port().isEnabled());
286 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
289 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
290 new DefaultPortDescription(P1, false),
291 new DefaultPortDescription(P2, true),
292 new DefaultPortDescription(P3, true)
295 events = deviceStore.updatePorts(PID, DID1, pds2);
296 assertFalse("event should be triggered", events.isEmpty());
297 for (DeviceEvent event : events) {
298 PortNumber num = event.port().number();
299 if (P1.equals(num)) {
300 assertEquals(PORT_UPDATED, event.type());
301 assertDevice(DID1, SW1, event.subject());
302 assertFalse("Port is disabled", event.port().isEnabled());
303 } else if (P2.equals(num)) {
304 fail("P2 event not expected.");
305 } else if (P3.equals(num)) {
306 assertEquals(PORT_ADDED, event.type());
307 assertDevice(DID1, SW1, event.subject());
308 assertTrue("Port is enabled", event.port().isEnabled());
310 fail("Unknown port number encountered: " + num);
314 List<PortDescription> pds3 = Arrays.<PortDescription>asList(
315 new DefaultPortDescription(P1, false),
316 new DefaultPortDescription(P2, true)
318 events = deviceStore.updatePorts(PID, DID1, pds3);
319 assertFalse("event should be triggered", events.isEmpty());
320 for (DeviceEvent event : events) {
321 PortNumber num = event.port().number();
322 if (P1.equals(num)) {
323 fail("P1 event not expected.");
324 } else if (P2.equals(num)) {
325 fail("P2 event not expected.");
326 } else if (P3.equals(num)) {
327 assertEquals(PORT_REMOVED, event.type());
328 assertDevice(DID1, SW1, event.subject());
329 assertTrue("Port was enabled", event.port().isEnabled());
331 fail("Unknown port number encountered: " + num);
338 public final void testUpdatePortStatus() {
339 putDevice(DID1, SW1);
340 List<PortDescription> pds = Arrays.<PortDescription>asList(
341 new DefaultPortDescription(P1, true)
343 deviceStore.updatePorts(PID, DID1, pds);
345 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
346 new DefaultPortDescription(P1, false));
347 assertEquals(PORT_UPDATED, event.type());
348 assertDevice(DID1, SW1, event.subject());
349 assertEquals(P1, event.port().number());
350 assertFalse("Port is disabled", event.port().isEnabled());
355 public final void testUpdatePortStatusAncillary() {
356 putDeviceAncillary(DID1, SW1);
357 putDevice(DID1, SW1);
358 List<PortDescription> pds = Arrays.<PortDescription>asList(
359 new DefaultPortDescription(P1, true, A1)
361 deviceStore.updatePorts(PID, DID1, pds);
363 DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
364 new DefaultPortDescription(P1, false, A1_2));
365 assertEquals(PORT_UPDATED, event.type());
366 assertDevice(DID1, SW1, event.subject());
367 assertEquals(P1, event.port().number());
368 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
369 assertFalse("Port is disabled", event.port().isEnabled());
371 DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1,
372 new DefaultPortDescription(P1, true));
373 assertNull("Ancillary is ignored if primary exists", event2);
375 // but, Ancillary annotation update will be notified
376 DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1,
377 new DefaultPortDescription(P1, true, A2));
378 assertEquals(PORT_UPDATED, event3.type());
379 assertDevice(DID1, SW1, event3.subject());
380 assertEquals(P1, event3.port().number());
381 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
382 assertFalse("Port is disabled", event3.port().isEnabled());
384 // port only reported from Ancillary will be notified as down
385 DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1,
386 new DefaultPortDescription(P2, true));
387 assertEquals(PORT_ADDED, event4.type());
388 assertDevice(DID1, SW1, event4.subject());
389 assertEquals(P2, event4.port().number());
390 assertAnnotationsEquals(event4.port().annotations());
391 assertFalse("Port is disabled if not given from primary provider",
392 event4.port().isEnabled());
396 public final void testGetPorts() {
397 putDevice(DID1, SW1);
398 putDevice(DID2, SW1);
399 List<PortDescription> pds = Arrays.<PortDescription>asList(
400 new DefaultPortDescription(P1, true),
401 new DefaultPortDescription(P2, true)
403 deviceStore.updatePorts(PID, DID1, pds);
405 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
406 List<Port> ports = deviceStore.getPorts(DID1);
407 for (Port port : ports) {
408 assertTrue("Port is enabled", port.isEnabled());
409 assertTrue("PortNumber is one of expected",
410 expectedPorts.remove(port.number()));
412 assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
415 assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
419 public final void testGetPort() {
420 putDevice(DID1, SW1);
421 putDevice(DID2, SW1);
422 List<PortDescription> pds = Arrays.<PortDescription>asList(
423 new DefaultPortDescription(P1, true),
424 new DefaultPortDescription(P2, false)
426 deviceStore.updatePorts(PID, DID1, pds);
428 Port port1 = deviceStore.getPort(DID1, P1);
429 assertEquals(P1, port1.number());
430 assertTrue("Port is enabled", port1.isEnabled());
432 Port port2 = deviceStore.getPort(DID1, P2);
433 assertEquals(P2, port2.number());
434 assertFalse("Port is disabled", port2.isEnabled());
436 Port port3 = deviceStore.getPort(DID1, P3);
437 assertNull("P3 not expected", port3);
441 public final void testRemoveDevice() {
442 putDevice(DID1, SW1, A1);
443 List<PortDescription> pds = Arrays.<PortDescription>asList(
444 new DefaultPortDescription(P1, true, A2)
446 deviceStore.updatePorts(PID, DID1, pds);
447 putDevice(DID2, SW1);
449 assertEquals(2, deviceStore.getDeviceCount());
450 assertEquals(1, deviceStore.getPorts(DID1).size());
451 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
452 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
454 DeviceEvent event = deviceStore.removeDevice(DID1);
455 assertEquals(DEVICE_REMOVED, event.type());
456 assertDevice(DID1, SW1, event.subject());
458 assertEquals(1, deviceStore.getDeviceCount());
459 assertEquals(0, deviceStore.getPorts(DID1).size());
461 // putBack Device, Port w/o annotation
462 putDevice(DID1, SW1);
463 List<PortDescription> pds2 = Arrays.<PortDescription>asList(
464 new DefaultPortDescription(P1, true)
466 deviceStore.updatePorts(PID, DID1, pds2);
468 // annotations should not survive
469 assertEquals(2, deviceStore.getDeviceCount());
470 assertEquals(1, deviceStore.getPorts(DID1).size());
471 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations());
472 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations());
475 // If Delegates should be called only on remote events,
476 // then Simple* should never call them, thus not test required.
477 // TODO add test for Port events when we have them
478 @Ignore("Ignore until Delegate spec. is clear.")
480 public final void testEvents() throws InterruptedException {
481 final CountDownLatch addLatch = new CountDownLatch(1);
482 DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() {
484 public void notify(DeviceEvent event) {
485 assertEquals(DEVICE_ADDED, event.type());
486 assertDevice(DID1, SW1, event.subject());
487 addLatch.countDown();
490 final CountDownLatch updateLatch = new CountDownLatch(1);
491 DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() {
493 public void notify(DeviceEvent event) {
494 assertEquals(DEVICE_UPDATED, event.type());
495 assertDevice(DID1, SW2, event.subject());
496 updateLatch.countDown();
499 final CountDownLatch removeLatch = new CountDownLatch(1);
500 DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() {
502 public void notify(DeviceEvent event) {
503 assertEquals(DEVICE_REMOVED, event.type());
504 assertDevice(DID1, SW2, event.subject());
505 removeLatch.countDown();
509 DeviceDescription description =
510 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
512 deviceStore.setDelegate(checkAdd);
513 deviceStore.createOrUpdateDevice(PID, DID1, description);
514 assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
517 DeviceDescription description2 =
518 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
520 deviceStore.unsetDelegate(checkAdd);
521 deviceStore.setDelegate(checkUpdate);
522 deviceStore.createOrUpdateDevice(PID, DID1, description2);
523 assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
525 deviceStore.unsetDelegate(checkUpdate);
526 deviceStore.setDelegate(checkRemove);
527 deviceStore.removeDevice(DID1);
528 assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));