Yuta HIGUCHI

Unit Tests for DistributedDeviceStore

Change-Id: Ie5a1b6bcefe2046cf13b818865327fa75dae4ec8
1 +/**
2 + *
3 + */
4 +package org.onlab.onos.store.device.impl;
5 +
6 +import static org.junit.Assert.*;
7 +import static org.onlab.onos.net.Device.Type.SWITCH;
8 +import static org.onlab.onos.net.DeviceId.deviceId;
9 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
10 +
11 +import java.util.Arrays;
12 +import java.util.HashMap;
13 +import java.util.List;
14 +import java.util.Map;
15 +import java.util.Set;
16 +import java.util.concurrent.CountDownLatch;
17 +import java.util.concurrent.TimeUnit;
18 +
19 +import org.junit.After;
20 +import org.junit.AfterClass;
21 +import org.junit.Before;
22 +import org.junit.BeforeClass;
23 +import org.junit.Test;
24 +import org.onlab.onos.net.Device;
25 +import org.onlab.onos.net.DeviceId;
26 +import org.onlab.onos.net.Port;
27 +import org.onlab.onos.net.PortNumber;
28 +import org.onlab.onos.net.device.DefaultDeviceDescription;
29 +import org.onlab.onos.net.device.DefaultPortDescription;
30 +import org.onlab.onos.net.device.DeviceDescription;
31 +import org.onlab.onos.net.device.DeviceEvent;
32 +import org.onlab.onos.net.device.DeviceStoreDelegate;
33 +import org.onlab.onos.net.device.PortDescription;
34 +import org.onlab.onos.net.provider.ProviderId;
35 +import org.onlab.onos.store.common.StoreService;
36 +import org.onlab.onos.store.impl.StoreManager;
37 +import org.onlab.onos.store.impl.TestStoreManager;
38 +
39 +import com.google.common.collect.Iterables;
40 +import com.google.common.collect.Sets;
41 +import com.hazelcast.config.Config;
42 +import com.hazelcast.core.Hazelcast;
43 +
44 +public class DistributedDeviceStoreTest {
45 +
46 + private static final ProviderId PID = new ProviderId("of", "foo");
47 + private static final DeviceId DID1 = deviceId("of:foo");
48 + private static final DeviceId DID2 = deviceId("of:bar");
49 + private static final String MFR = "whitebox";
50 + private static final String HW = "1.1.x";
51 + private static final String SW1 = "3.8.1";
52 + private static final String SW2 = "3.9.5";
53 + private static final String SN = "43311-12345";
54 +
55 + private static final PortNumber P1 = PortNumber.portNumber(1);
56 + private static final PortNumber P2 = PortNumber.portNumber(2);
57 + private static final PortNumber P3 = PortNumber.portNumber(3);
58 +
59 + private DistributedDeviceStore deviceStore;
60 +
61 + private StoreManager storeManager;
62 +
63 +
64 + @BeforeClass
65 + public static void setUpBeforeClass() throws Exception {
66 + }
67 +
68 + @AfterClass
69 + public static void tearDownAfterClass() throws Exception {
70 + }
71 +
72 +
73 + @Before
74 + public void setUp() throws Exception {
75 + // TODO should find a way to clean Hazelcast instance without shutdown.
76 + Config config = TestStoreManager.getTestConfig();
77 +
78 + storeManager = new TestStoreManager(Hazelcast.newHazelcastInstance(config));
79 + storeManager.activate();
80 +
81 + deviceStore = new TestDistributedDeviceStore(storeManager);
82 + deviceStore.activate();
83 + }
84 +
85 + @After
86 + public void tearDown() throws Exception {
87 + deviceStore.deactivate();
88 +
89 + storeManager.deactivate();
90 + }
91 +
92 + private void putDevice(DeviceId deviceId, String swVersion) {
93 + DeviceDescription description =
94 + new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
95 + HW, swVersion, SN);
96 + deviceStore.createOrUpdateDevice(PID, deviceId, description);
97 + }
98 +
99 + private static void assertDevice(DeviceId id, String swVersion, Device device) {
100 + assertNotNull(device);
101 + assertEquals(id, device.id());
102 + assertEquals(MFR, device.manufacturer());
103 + assertEquals(HW, device.hwVersion());
104 + assertEquals(swVersion, device.swVersion());
105 + assertEquals(SN, device.serialNumber());
106 + }
107 +
108 + @Test
109 + public final void testGetDeviceCount() {
110 + assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
111 +
112 + putDevice(DID1, SW1);
113 + putDevice(DID2, SW2);
114 + putDevice(DID1, SW1);
115 +
116 + assertEquals("expect 2 uniq devices", 2, deviceStore.getDeviceCount());
117 + }
118 +
119 + @Test
120 + public final void testGetDevices() {
121 + assertEquals("initialy empty", 0, Iterables.size(deviceStore.getDevices()));
122 +
123 + putDevice(DID1, SW1);
124 + putDevice(DID2, SW2);
125 + putDevice(DID1, SW1);
126 +
127 + assertEquals("expect 2 uniq devices",
128 + 2, Iterables.size(deviceStore.getDevices()));
129 +
130 + Map<DeviceId, Device> devices = new HashMap<>();
131 + for (Device device : deviceStore.getDevices()) {
132 + devices.put(device.id(), device);
133 + }
134 +
135 + assertDevice(DID1, SW1, devices.get(DID1));
136 + assertDevice(DID2, SW2, devices.get(DID2));
137 +
138 + // add case for new node?
139 + }
140 +
141 + @Test
142 + public final void testGetDevice() {
143 +
144 + putDevice(DID1, SW1);
145 +
146 + assertDevice(DID1, SW1, deviceStore.getDevice(DID1));
147 + assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
148 + }
149 +
150 + @Test
151 + public final void testCreateOrUpdateDevice() {
152 + DeviceDescription description =
153 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
154 + HW, SW1, SN);
155 + DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
156 + assertEquals(DEVICE_ADDED, event.type());
157 + assertDevice(DID1, SW1, event.subject());
158 +
159 + DeviceDescription description2 =
160 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
161 + HW, SW2, SN);
162 + DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
163 + assertEquals(DEVICE_UPDATED, event2.type());
164 + assertDevice(DID1, SW2, event2.subject());
165 +
166 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
167 + }
168 +
169 + @Test
170 + public final void testMarkOffline() {
171 +
172 + putDevice(DID1, SW1);
173 + assertTrue(deviceStore.isAvailable(DID1));
174 +
175 + DeviceEvent event = deviceStore.markOffline(DID1);
176 + assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
177 + assertDevice(DID1, SW1, event.subject());
178 + assertFalse(deviceStore.isAvailable(DID1));
179 +
180 + DeviceEvent event2 = deviceStore.markOffline(DID1);
181 + assertNull("No change, no event", event2);
182 +}
183 +
184 + @Test
185 + public final void testUpdatePorts() {
186 + putDevice(DID1, SW1);
187 + List<PortDescription> pds = Arrays.<PortDescription>asList(
188 + new DefaultPortDescription(P1, true),
189 + new DefaultPortDescription(P2, true)
190 + );
191 +
192 + List<DeviceEvent> events = deviceStore.updatePorts(DID1, pds);
193 +
194 + Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
195 + for (DeviceEvent event : events) {
196 + assertEquals(PORT_ADDED, event.type());
197 + assertDevice(DID1, SW1, event.subject());
198 + assertTrue("PortNumber is one of expected",
199 + expectedPorts.remove(event.port().number()));
200 + assertTrue("Port is enabled", event.port().isEnabled());
201 + }
202 + assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
203 +
204 +
205 + List<PortDescription> pds2 = Arrays.<PortDescription>asList(
206 + new DefaultPortDescription(P1, false),
207 + new DefaultPortDescription(P2, true),
208 + new DefaultPortDescription(P3, true)
209 + );
210 +
211 + events = deviceStore.updatePorts(DID1, pds2);
212 + assertFalse("event should be triggered", events.isEmpty());
213 + for (DeviceEvent event : events) {
214 + PortNumber num = event.port().number();
215 + if (P1.equals(num)) {
216 + assertEquals(PORT_UPDATED, event.type());
217 + assertDevice(DID1, SW1, event.subject());
218 + assertFalse("Port is disabled", event.port().isEnabled());
219 + } else if (P2.equals(num)) {
220 + fail("P2 event not expected.");
221 + } else if (P3.equals(num)) {
222 + assertEquals(PORT_ADDED, event.type());
223 + assertDevice(DID1, SW1, event.subject());
224 + assertTrue("Port is enabled", event.port().isEnabled());
225 + } else {
226 + fail("Unknown port number encountered: " + num);
227 + }
228 + }
229 +
230 + List<PortDescription> pds3 = Arrays.<PortDescription>asList(
231 + new DefaultPortDescription(P1, false),
232 + new DefaultPortDescription(P2, true)
233 + );
234 + events = deviceStore.updatePorts(DID1, pds3);
235 + assertFalse("event should be triggered", events.isEmpty());
236 + for (DeviceEvent event : events) {
237 + PortNumber num = event.port().number();
238 + if (P1.equals(num)) {
239 + fail("P1 event not expected.");
240 + } else if (P2.equals(num)) {
241 + fail("P2 event not expected.");
242 + } else if (P3.equals(num)) {
243 + assertEquals(PORT_REMOVED, event.type());
244 + assertDevice(DID1, SW1, event.subject());
245 + assertTrue("Port was enabled", event.port().isEnabled());
246 + } else {
247 + fail("Unknown port number encountered: " + num);
248 + }
249 + }
250 +
251 + }
252 +
253 + @Test
254 + public final void testUpdatePortStatus() {
255 + putDevice(DID1, SW1);
256 + List<PortDescription> pds = Arrays.<PortDescription>asList(
257 + new DefaultPortDescription(P1, true)
258 + );
259 + deviceStore.updatePorts(DID1, pds);
260 +
261 + DeviceEvent event = deviceStore.updatePortStatus(DID1,
262 + new DefaultPortDescription(P1, false));
263 + assertEquals(PORT_UPDATED, event.type());
264 + assertDevice(DID1, SW1, event.subject());
265 + assertEquals(P1, event.port().number());
266 + assertFalse("Port is disabled", event.port().isEnabled());
267 + }
268 +
269 + @Test
270 + public final void testGetPorts() {
271 + putDevice(DID1, SW1);
272 + putDevice(DID2, SW1);
273 + List<PortDescription> pds = Arrays.<PortDescription>asList(
274 + new DefaultPortDescription(P1, true),
275 + new DefaultPortDescription(P2, true)
276 + );
277 + deviceStore.updatePorts(DID1, pds);
278 +
279 + Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
280 + List<Port> ports = deviceStore.getPorts(DID1);
281 + for (Port port : ports) {
282 + assertTrue("Port is enabled", port.isEnabled());
283 + assertTrue("PortNumber is one of expected",
284 + expectedPorts.remove(port.number()));
285 + }
286 + assertTrue("Event for all expectedport appeared", expectedPorts.isEmpty());
287 +
288 +
289 + assertTrue("DID2 has no ports", deviceStore.getPorts(DID2).isEmpty());
290 + }
291 +
292 + @Test
293 + public final void testGetPort() {
294 + putDevice(DID1, SW1);
295 + putDevice(DID2, SW1);
296 + List<PortDescription> pds = Arrays.<PortDescription>asList(
297 + new DefaultPortDescription(P1, true),
298 + new DefaultPortDescription(P2, false)
299 + );
300 + deviceStore.updatePorts(DID1, pds);
301 +
302 + Port port1 = deviceStore.getPort(DID1, P1);
303 + assertEquals(P1, port1.number());
304 + assertTrue("Port is enabled", port1.isEnabled());
305 +
306 + Port port2 = deviceStore.getPort(DID1, P2);
307 + assertEquals(P2, port2.number());
308 + assertFalse("Port is disabled", port2.isEnabled());
309 +
310 + Port port3 = deviceStore.getPort(DID1, P3);
311 + assertNull("P3 not expected", port3);
312 + }
313 +
314 + @Test
315 + public final void testRemoveDevice() {
316 + putDevice(DID1, SW1);
317 + putDevice(DID2, SW1);
318 +
319 + assertEquals(2, deviceStore.getDeviceCount());
320 +
321 + DeviceEvent event = deviceStore.removeDevice(DID1);
322 + assertEquals(DEVICE_REMOVED, event.type());
323 + assertDevice(DID1, SW1, event.subject());
324 +
325 + assertEquals(1, deviceStore.getDeviceCount());
326 + }
327 +
328 + // TODO add test for Port events when we have them
329 + @Test
330 + public final void testEvents() throws InterruptedException {
331 + final CountDownLatch addLatch = new CountDownLatch(1);
332 + DeviceStoreDelegate checkAdd = new DeviceStoreDelegate() {
333 + @Override
334 + public void notify(DeviceEvent event) {
335 + assertEquals(DEVICE_ADDED, event.type());
336 + assertDevice(DID1, SW1, event.subject());
337 + addLatch.countDown();
338 + }
339 + };
340 + final CountDownLatch updateLatch = new CountDownLatch(1);
341 + DeviceStoreDelegate checkUpdate = new DeviceStoreDelegate() {
342 + @Override
343 + public void notify(DeviceEvent event) {
344 + assertEquals(DEVICE_UPDATED, event.type());
345 + assertDevice(DID1, SW2, event.subject());
346 + updateLatch.countDown();
347 + }
348 + };
349 + final CountDownLatch removeLatch = new CountDownLatch(1);
350 + DeviceStoreDelegate checkRemove = new DeviceStoreDelegate() {
351 + @Override
352 + public void notify(DeviceEvent event) {
353 + assertEquals(DEVICE_REMOVED, event.type());
354 + assertDevice(DID1, SW2, event.subject());
355 + removeLatch.countDown();
356 + }
357 + };
358 +
359 + DeviceDescription description =
360 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
361 + HW, SW1, SN);
362 + deviceStore.setDelegate(checkAdd);
363 + deviceStore.createOrUpdateDevice(PID, DID1, description);
364 + assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
365 +
366 +
367 + DeviceDescription description2 =
368 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
369 + HW, SW2, SN);
370 + deviceStore.unsetDelegate(checkAdd);
371 + deviceStore.setDelegate(checkUpdate);
372 + deviceStore.createOrUpdateDevice(PID, DID1, description2);
373 + assertTrue("Update event fired", updateLatch.await(1, TimeUnit.SECONDS));
374 +
375 + deviceStore.unsetDelegate(checkUpdate);
376 + deviceStore.setDelegate(checkRemove);
377 + deviceStore.removeDevice(DID1);
378 + assertTrue("Remove event fired", removeLatch.await(1, TimeUnit.SECONDS));
379 + }
380 +
381 + private class TestDistributedDeviceStore extends DistributedDeviceStore {
382 + public TestDistributedDeviceStore(StoreService storeService) {
383 + this.storeService = storeService;
384 + }
385 + }
386 +}