562e6f3c97ddaa2afce2905b1e58a90a66b5f4dd
[onosfw.git] /
1 /*
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  */
16
17 /**
18  *
19  */
20 package org.onosproject.store.trivial;
21
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;
27
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.TimeUnit;
35
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;
56
57 import com.google.common.collect.Iterables;
58 import com.google.common.collect.Sets;
59
60 import org.onlab.packet.ChassisId;
61
62 /**
63  * Test of the simple DeviceStore implementation.
64  */
65 public class SimpleDeviceStoreTest {
66
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();
77
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);
81
82     private static final SparseAnnotations A1 = DefaultAnnotations.builder()
83             .set("A1", "a1")
84             .set("B1", "b1")
85             .build();
86     private static final SparseAnnotations A1_2 = DefaultAnnotations.builder()
87             .remove("A1")
88             .set("B3", "b3")
89             .build();
90     private static final SparseAnnotations A2 = DefaultAnnotations.builder()
91             .set("A2", "a2")
92             .set("B2", "b2")
93             .build();
94     private static final SparseAnnotations A2_2 = DefaultAnnotations.builder()
95             .remove("A2")
96             .set("B4", "b4")
97             .build();
98
99     private SimpleDeviceStore simpleDeviceStore;
100     private DeviceStore deviceStore;
101
102
103
104     @BeforeClass
105     public static void setUpBeforeClass() throws Exception {
106     }
107
108     @AfterClass
109     public static void tearDownAfterClass() throws Exception {
110     }
111
112
113     @Before
114     public void setUp() throws Exception {
115         simpleDeviceStore = new SimpleDeviceStore();
116         simpleDeviceStore.activate();
117         deviceStore = simpleDeviceStore;
118     }
119
120     @After
121     public void tearDown() throws Exception {
122         simpleDeviceStore.deactivate();
123     }
124
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);
131     }
132
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);
139     }
140
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());
148     }
149
150     @Test
151     public final void testGetDeviceCount() {
152         assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
153
154         putDevice(DID1, SW1);
155         putDevice(DID2, SW2);
156         putDevice(DID1, SW1);
157
158         assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
159     }
160
161     @Test
162     public final void testGetDevices() {
163         assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
164
165         putDevice(DID1, SW1);
166         putDevice(DID2, SW2);
167         putDevice(DID1, SW1);
168
169         assertEquals("expect 2 uniq devices",
170                 2, Iterables.size(deviceStore.getDevices()));
171
172         Map<DeviceId, Device> devices = new HashMap<>();
173         for (Device device : deviceStore.getDevices()) {
174             devices.put(device.id(), device);
175         }
176
177         assertDevice(DID1, SW1, devices.get(DID1));
178         assertDevice(DID2, SW2, devices.get(DID2));
179
180         // add case for new node?
181     }
182
183     @Test
184     public final void testGetDevice() {
185
186         putDevice(DID1, SW1);
187
188         assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
189         assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
190     }
191
192     @Test
193     public final void testCreateOrUpdateDevice() {
194         DeviceDescription description =
195                 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
196                         HW, SW1, SN, CID);
197         DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
198         assertEquals(DEVICE_ADDED, event.type());
199         assertDevice(DID1, SW1, event.subject());
200
201         DeviceDescription description2 =
202                 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
203                         HW, SW2, SN, CID);
204         DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
205         assertEquals(DEVICE_UPDATED, event2.type());
206         assertDevice(DID1, SW2, event2.subject());
207
208         assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
209     }
210
211     @Test
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));
222
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));
232
233         assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
234
235         // For now, Ancillary is ignored once primary appears
236         assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
237
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));
250     }
251
252
253     @Test
254     public final void testMarkOffline() {
255
256         putDevice(DID1, SW1);
257         assertTrue(deviceStore.isAvailable(DID1));
258
259         DeviceEvent event = deviceStore.markOffline(DID1);
260         assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
261         assertDevice(DID1, SW1, event.subject());
262         assertFalse(deviceStore.isAvailable(DID1));
263
264         DeviceEvent event2 = deviceStore.markOffline(DID1);
265         assertNull("No change, no event", event2);
266 }
267
268     @Test
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)
274                 );
275
276         List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
277
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());
285         }
286         assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
287
288
289         List<PortDescription> pds2 = Arrays.<PortDescription>asList(
290                 new DefaultPortDescription(P1, false),
291                 new DefaultPortDescription(P2, true),
292                 new DefaultPortDescription(P3, true)
293                 );
294
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());
309             } else {
310                 fail("Unknown port number encountered: " + num);
311             }
312         }
313
314         List<PortDescription> pds3 = Arrays.<PortDescription>asList(
315                 new DefaultPortDescription(P1, false),
316                 new DefaultPortDescription(P2, true)
317                 );
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());
330             } else {
331                 fail("Unknown port number encountered: " + num);
332             }
333         }
334
335     }
336
337     @Test
338     public final void testUpdatePortStatus() {
339         putDevice(DID1, SW1);
340         List<PortDescription> pds = Arrays.<PortDescription>asList(
341                 new DefaultPortDescription(P1, true)
342                 );
343         deviceStore.updatePorts(PID, DID1, pds);
344
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());
351
352     }
353
354     @Test
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)
360                 );
361         deviceStore.updatePorts(PID, DID1, pds);
362
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());
370
371         DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1,
372                 new DefaultPortDescription(P1, true));
373         assertNull("Ancillary is ignored if primary exists", event2);
374
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());
383
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());
393     }
394
395     @Test
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)
402                 );
403         deviceStore.updatePorts(PID, DID1, pds);
404
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()));
411         }
412         assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
413
414
415         assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
416     }
417
418     @Test
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)
425                 );
426         deviceStore.updatePorts(PID, DID1, pds);
427
428         Port port1 = deviceStore.getPort(DID1, P1);
429         assertEquals(P1, port1.number());
430         assertTrue("Port is enabled", port1.isEnabled());
431
432         Port port2 = deviceStore.getPort(DID1, P2);
433         assertEquals(P2, port2.number());
434         assertFalse("Port is disabled", port2.isEnabled());
435
436         Port port3 = deviceStore.getPort(DID1, P3);
437         assertNull("P3 not expected", port3);
438     }
439
440     @Test
441     public final void testRemoveDevice() {
442         putDevice(DID1, SW1, A1);
443         List<PortDescription> pds = Arrays.<PortDescription>asList(
444                 new DefaultPortDescription(P1, true, A2)
445                 );
446         deviceStore.updatePorts(PID, DID1, pds);
447         putDevice(DID2, SW1);
448
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);
453
454         DeviceEvent event = deviceStore.removeDevice(DID1);
455         assertEquals(DEVICE_REMOVED, event.type());
456         assertDevice(DID1, SW1, event.subject());
457
458         assertEquals(1, deviceStore.getDeviceCount());
459         assertEquals(0, deviceStore.getPorts(DID1).size());
460
461         // putBack Device, Port w/o annotation
462         putDevice(DID1, SW1);
463         List<PortDescription> pds2 = Arrays.<PortDescription>asList(
464                 new DefaultPortDescription(P1, true)
465                 );
466         deviceStore.updatePorts(PID, DID1, pds2);
467
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());
473     }
474
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.")
479     @Test
480     public final void testEvents() throws InterruptedException {
481         final CountDownLatch addLatch = new CountDownLatch(1);
482         DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() {
483             @Override
484             public void notify(DeviceEvent event) {
485                 assertEquals(DEVICE_ADDED, event.type());
486                 assertDevice(DID1, SW1, event.subject());
487                 addLatch.countDown();
488             }
489         };
490         final CountDownLatch updateLatch = new CountDownLatch(1);
491         DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() {
492             @Override
493             public void notify(DeviceEvent event) {
494                 assertEquals(DEVICE_UPDATED, event.type());
495                 assertDevice(DID1, SW2, event.subject());
496                 updateLatch.countDown();
497             }
498         };
499         final CountDownLatch removeLatch = new CountDownLatch(1);
500         DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() {
501             @Override
502             public void notify(DeviceEvent event) {
503                 assertEquals(DEVICE_REMOVED, event.type());
504                 assertDevice(DID1, SW2, event.subject());
505                 removeLatch.countDown();
506             }
507         };
508
509         DeviceDescription description =
510                 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
511                         HW, SW1, SN, CID);
512         deviceStore.setDelegate(checkAdd);
513         deviceStore.createOrUpdateDevice(PID, DID1, description);
514         assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
515
516
517         DeviceDescription description2 =
518                 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
519                         HW, SW2, SN, CID);
520         deviceStore.unsetDelegate(checkAdd);
521         deviceStore.setDelegate(checkUpdate);
522         deviceStore.createOrUpdateDevice(PID, DID1, description2);
523         assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
524
525         deviceStore.unsetDelegate(checkUpdate);
526         deviceStore.setDelegate(checkRemove);
527         deviceStore.removeDevice(DID1);
528         assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
529     }
530 }