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