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