blob: 332634f82db8b435d0c93fc06c0ccf6f246195ee [file] [log] [blame]
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -07001package org.onlab.onos.net.device.impl;
2
tom0872a172014-09-23 11:24:26 -07003import com.google.common.collect.Iterables;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -07004import com.google.common.collect.Sets;
tom0872a172014-09-23 11:24:26 -07005import com.hazelcast.config.Config;
6import com.hazelcast.core.Hazelcast;
tom85ff08b2014-09-22 17:14:18 -07007import com.hazelcast.core.HazelcastInstance;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -07008
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -07009import org.junit.After;
10import org.junit.Before;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070011import org.junit.Test;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070012import org.onlab.onos.cluster.MastershipListener;
13import org.onlab.onos.cluster.MastershipService;
14import org.onlab.onos.cluster.NodeId;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070015import org.onlab.onos.event.Event;
tom0872a172014-09-23 11:24:26 -070016import org.onlab.onos.event.impl.TestEventDispatcher;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070017import org.onlab.onos.net.Device;
18import org.onlab.onos.net.DeviceId;
19import org.onlab.onos.net.MastershipRole;
20import org.onlab.onos.net.Port;
21import org.onlab.onos.net.PortNumber;
22import org.onlab.onos.net.device.DefaultDeviceDescription;
23import org.onlab.onos.net.device.DefaultPortDescription;
24import org.onlab.onos.net.device.DeviceAdminService;
25import org.onlab.onos.net.device.DeviceDescription;
26import org.onlab.onos.net.device.DeviceEvent;
27import org.onlab.onos.net.device.DeviceListener;
28import org.onlab.onos.net.device.DeviceProvider;
29import org.onlab.onos.net.device.DeviceProviderRegistry;
30import org.onlab.onos.net.device.DeviceProviderService;
31import org.onlab.onos.net.device.DeviceService;
32import org.onlab.onos.net.device.PortDescription;
33import org.onlab.onos.net.provider.AbstractProvider;
34import org.onlab.onos.net.provider.ProviderId;
tom85ff08b2014-09-22 17:14:18 -070035import org.onlab.onos.store.StoreService;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070036import org.onlab.onos.store.device.impl.DistributedDeviceStore;
tom0872a172014-09-23 11:24:26 -070037import org.onlab.onos.store.impl.StoreManager;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070038
39import java.util.ArrayList;
40import java.util.Iterator;
41import java.util.List;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070042import java.util.Set;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070043import java.util.UUID;
44
45import static org.junit.Assert.*;
46import static org.onlab.onos.net.Device.Type.SWITCH;
47import static org.onlab.onos.net.DeviceId.deviceId;
48import static org.onlab.onos.net.device.DeviceEvent.Type.*;
49
50// FIXME This test is painfully slow starting up Hazelcast on each test cases,
51// turning it off in repository for now.
52// FIXME DistributedDeviceStore should have it's own test cases.
53/**
54 * Test codifying the device service & device provider service contracts.
55 */
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070056public class DistributedDeviceManagerTest {
57
58 private static final ProviderId PID = new ProviderId("of", "foo");
59 private static final DeviceId DID1 = deviceId("of:foo");
60 private static final DeviceId DID2 = deviceId("of:bar");
61 private static final String MFR = "whitebox";
62 private static final String HW = "1.1.x";
63 private static final String SW1 = "3.8.1";
64 private static final String SW2 = "3.9.5";
65 private static final String SN = "43311-12345";
66
67 private static final PortNumber P1 = PortNumber.portNumber(1);
68 private static final PortNumber P2 = PortNumber.portNumber(2);
69 private static final PortNumber P3 = PortNumber.portNumber(3);
70
71 private DeviceManager mgr;
72
tom0872a172014-09-23 11:24:26 -070073 protected StoreManager storeManager;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070074 protected DeviceService service;
75 protected DeviceAdminService admin;
76 protected DeviceProviderRegistry registry;
77 protected DeviceProviderService providerService;
78 protected TestProvider provider;
79 protected TestListener listener = new TestListener();
80 private DistributedDeviceStore dstore;
81
82 @Before
83 public void setUp() {
84 mgr = new DeviceManager();
85 service = mgr;
86 admin = mgr;
87 registry = mgr;
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -070088 // FIXME should be reading the hazelcast.xml
89 Config config = new Config();
90 // avoid accidentally joining other cluster
91 config.getGroupConfig().setName(UUID.randomUUID().toString());
92 // quickly form single node cluster
Yuta HIGUCHI1b9f4dc2014-09-22 10:25:06 -070093 config.getNetworkConfig().getJoin()
94 .getTcpIpConfig()
95 .setEnabled(true).setConnectionTimeoutSeconds(0);
96 config.getNetworkConfig().getJoin()
97 .getMulticastConfig()
98 .setEnabled(false);
tom0872a172014-09-23 11:24:26 -070099
100 storeManager = new TestStoreManager(Hazelcast.newHazelcastInstance(config));
101 storeManager.activate();
102
103 dstore = new TestDistributedDeviceStore(storeManager);
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -0700104 dstore.activate();
105 mgr.store = dstore;
106 mgr.eventDispatcher = new TestEventDispatcher();
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700107 mgr.mastershipService = new TestMastershipService();
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -0700108 mgr.activate();
109
110 service.addListener(listener);
111
112 provider = new TestProvider();
113 providerService = registry.register(provider);
114 assertTrue("provider should be registered",
115 registry.getProviders().contains(provider.id()));
116 }
117
118 @After
119 public void tearDown() {
120 registry.unregister(provider);
121 assertFalse("provider should not be registered",
122 registry.getProviders().contains(provider.id()));
123 service.removeListener(listener);
124 mgr.deactivate();
125
126 dstore.deactivate();
tom0872a172014-09-23 11:24:26 -0700127 storeManager.deactivate();
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -0700128 }
129
130 private void connectDevice(DeviceId deviceId, String swVersion) {
131 DeviceDescription description =
132 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
133 HW, swVersion, SN);
134 providerService.deviceConnected(deviceId, description);
135 assertNotNull("device should be found", service.getDevice(DID1));
136 }
137
138 @Test
139 public void deviceConnected() {
140 assertNull("device should not be found", service.getDevice(DID1));
141 connectDevice(DID1, SW1);
142 validateEvents(DEVICE_ADDED);
143
144 assertEquals("only one device expected", 1, Iterables.size(service.getDevices()));
145 Iterator<Device> it = service.getDevices().iterator();
146 assertNotNull("one device expected", it.next());
147 assertFalse("only one device expected", it.hasNext());
148
149 assertEquals("incorrect device count", 1, service.getDeviceCount());
150 assertTrue("device should be available", service.isAvailable(DID1));
151 }
152
153 @Test
154 public void deviceDisconnected() {
155 connectDevice(DID1, SW1);
156 connectDevice(DID2, SW1);
157 validateEvents(DEVICE_ADDED, DEVICE_ADDED);
158 assertTrue("device should be available", service.isAvailable(DID1));
159
160 // Disconnect
161 providerService.deviceDisconnected(DID1);
162 assertNotNull("device should not be found", service.getDevice(DID1));
163 assertFalse("device should not be available", service.isAvailable(DID1));
164 validateEvents(DEVICE_AVAILABILITY_CHANGED);
165
166 // Reconnect
167 connectDevice(DID1, SW1);
168 validateEvents(DEVICE_AVAILABILITY_CHANGED);
169
170 assertEquals("incorrect device count", 2, service.getDeviceCount());
171 }
172
173 @Test
174 public void deviceUpdated() {
175 connectDevice(DID1, SW1);
176 validateEvents(DEVICE_ADDED);
177
178 connectDevice(DID1, SW2);
179 validateEvents(DEVICE_UPDATED);
180 }
181
182 @Test
183 public void getRole() {
184 connectDevice(DID1, SW1);
185 assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
186 }
187
188 @Test
189 public void setRole() throws InterruptedException {
190 connectDevice(DID1, SW1);
191 admin.setRole(DID1, MastershipRole.STANDBY);
192 validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED);
193 assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1));
194 assertEquals("incorrect device", DID1, provider.deviceReceived.id());
195 assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived);
196 }
197
198 @Test
199 public void updatePorts() {
200 connectDevice(DID1, SW1);
201 List<PortDescription> pds = new ArrayList<>();
202 pds.add(new DefaultPortDescription(P1, true));
203 pds.add(new DefaultPortDescription(P2, true));
204 pds.add(new DefaultPortDescription(P3, true));
205 providerService.updatePorts(DID1, pds);
206 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED);
207 pds.clear();
208
209 pds.add(new DefaultPortDescription(P1, false));
210 pds.add(new DefaultPortDescription(P3, true));
211 providerService.updatePorts(DID1, pds);
212 validateEvents(PORT_UPDATED, PORT_REMOVED);
213 }
214
215 @Test
216 public void updatePortStatus() {
217 connectDevice(DID1, SW1);
218 List<PortDescription> pds = new ArrayList<>();
219 pds.add(new DefaultPortDescription(P1, true));
220 pds.add(new DefaultPortDescription(P2, true));
221 providerService.updatePorts(DID1, pds);
222 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
223
224 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false));
225 validateEvents(PORT_UPDATED);
226 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false));
227 assertTrue("no events expected", listener.events.isEmpty());
228 }
229
230 @Test
231 public void getPorts() {
232 connectDevice(DID1, SW1);
233 List<PortDescription> pds = new ArrayList<>();
234 pds.add(new DefaultPortDescription(P1, true));
235 pds.add(new DefaultPortDescription(P2, true));
236 providerService.updatePorts(DID1, pds);
237 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
238 assertEquals("wrong port count", 2, service.getPorts(DID1).size());
239
240 Port port = service.getPort(DID1, P1);
241 assertEquals("incorrect port", P1, service.getPort(DID1, P1).number());
242 assertEquals("incorrect state", true, service.getPort(DID1, P1).isEnabled());
243 }
244
245 @Test
246 public void removeDevice() {
247 connectDevice(DID1, SW1);
248 connectDevice(DID2, SW2);
249 assertEquals("incorrect device count", 2, service.getDeviceCount());
250 admin.removeDevice(DID1);
251 assertNull("device should not be found", service.getDevice(DID1));
252 assertNotNull("device should be found", service.getDevice(DID2));
253 assertEquals("incorrect device count", 1, service.getDeviceCount());
254
255 }
256
257 protected void validateEvents(Enum... types) {
258 int i = 0;
259 assertEquals("wrong events received", types.length, listener.events.size());
260 for (Event event : listener.events) {
261 assertEquals("incorrect event type", types[i], event.type());
262 i++;
263 }
264 listener.events.clear();
265 }
266
267
268 private class TestProvider extends AbstractProvider implements DeviceProvider {
269 private Device deviceReceived;
270 private MastershipRole roleReceived;
271
272 public TestProvider() {
273 super(PID);
274 }
275
276 @Override
277 public void triggerProbe(Device device) {
278 }
279
280 @Override
281 public void roleChanged(Device device, MastershipRole newRole) {
282 deviceReceived = device;
283 roleReceived = newRole;
284 }
285 }
286
287 private static class TestListener implements DeviceListener {
288 final List<DeviceEvent> events = new ArrayList<>();
289
290 @Override
291 public void event(DeviceEvent event) {
292 events.add(event);
293 }
294 }
295
tom85ff08b2014-09-22 17:14:18 -0700296 private class TestDistributedDeviceStore extends DistributedDeviceStore {
tom0872a172014-09-23 11:24:26 -0700297 public TestDistributedDeviceStore(StoreService storeService) {
298 this.storeService = storeService;
299 }
300 }
301
302 private class TestStoreManager extends StoreManager {
303 TestStoreManager(HazelcastInstance instance) {
304 this.instance = instance;
tom85ff08b2014-09-22 17:14:18 -0700305 }
Yuta HIGUCHIc7052012014-09-22 19:11:00 -0700306
tom0872a172014-09-23 11:24:26 -0700307 @Override
308 public void activate() {
309 setupKryoPool();
Yuta HIGUCHIc7052012014-09-22 19:11:00 -0700310 }
tom85ff08b2014-09-22 17:14:18 -0700311 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700312
313 private static class TestMastershipService implements MastershipService {
314
315 @Override
316 public NodeId getMasterFor(DeviceId deviceId) {
317 return null;
318 }
319
320 @Override
321 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
322 return Sets.newHashSet(DID1, DID2);
323 }
324
325 @Override
326 public MastershipRole requestRoleFor(DeviceId deviceId) {
327 return MastershipRole.MASTER;
328 }
329
330 @Override
331 public void addListener(MastershipListener listener) {
332 }
333
334 @Override
335 public void removeListener(MastershipListener listener) {
336 }
337
338 }
339
Yuta HIGUCHIb3b2ac42014-09-21 23:37:11 -0700340}