blob: d278c247fc1a885a4fb149e170b773e1c2664fd8 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
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 */
tombe988312014-09-19 18:38:47 -070016package org.onlab.onos.net.device.impl;
tome5ec3fd2014-09-04 15:18:06 -070017
tomb41d1ac2014-09-24 01:51:24 -070018import com.google.common.collect.Sets;
Ayaka Koshibec4047702014-10-07 14:43:52 -070019
tome5ec3fd2014-09-04 15:18:06 -070020import org.junit.After;
21import org.junit.Before;
22import org.junit.Test;
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -070023import org.onlab.onos.cluster.ClusterEventListener;
24import org.onlab.onos.cluster.ClusterService;
25import org.onlab.onos.cluster.ControllerNode;
26import org.onlab.onos.cluster.DefaultControllerNode;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070027import org.onlab.onos.cluster.NodeId;
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -070028import org.onlab.onos.cluster.ControllerNode.State;
tome5ec3fd2014-09-04 15:18:06 -070029import org.onlab.onos.event.Event;
tomb41d1ac2014-09-24 01:51:24 -070030import org.onlab.onos.event.impl.TestEventDispatcher;
Yuta HIGUCHI80912e62014-10-12 00:15:47 -070031import org.onlab.onos.mastership.MastershipServiceAdapter;
32import org.onlab.onos.mastership.MastershipTerm;
33import org.onlab.onos.mastership.MastershipTermService;
tome5ec3fd2014-09-04 15:18:06 -070034import org.onlab.onos.net.Device;
35import org.onlab.onos.net.DeviceId;
36import org.onlab.onos.net.MastershipRole;
tom24c55cd2014-09-06 10:47:25 -070037import org.onlab.onos.net.Port;
38import org.onlab.onos.net.PortNumber;
tome5ec3fd2014-09-04 15:18:06 -070039import org.onlab.onos.net.device.DefaultDeviceDescription;
tom24c55cd2014-09-06 10:47:25 -070040import org.onlab.onos.net.device.DefaultPortDescription;
tome5ec3fd2014-09-04 15:18:06 -070041import org.onlab.onos.net.device.DeviceAdminService;
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -070042import org.onlab.onos.net.device.DeviceClockProviderService;
tome5ec3fd2014-09-04 15:18:06 -070043import org.onlab.onos.net.device.DeviceDescription;
44import org.onlab.onos.net.device.DeviceEvent;
45import org.onlab.onos.net.device.DeviceListener;
46import org.onlab.onos.net.device.DeviceProvider;
47import org.onlab.onos.net.device.DeviceProviderRegistry;
48import org.onlab.onos.net.device.DeviceProviderService;
49import org.onlab.onos.net.device.DeviceService;
tom24c55cd2014-09-06 10:47:25 -070050import org.onlab.onos.net.device.PortDescription;
tome5ec3fd2014-09-04 15:18:06 -070051import org.onlab.onos.net.provider.AbstractProvider;
52import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070053import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
alshabib7911a052014-10-16 17:49:37 -070054import org.onlab.packet.ChassisId;
Pavlin Radoslavov444b5192014-10-28 10:45:19 -070055import org.onlab.packet.IpAddress;
tome5ec3fd2014-09-04 15:18:06 -070056
57import java.util.ArrayList;
58import java.util.Iterator;
59import java.util.List;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070060import java.util.Set;
tome5ec3fd2014-09-04 15:18:06 -070061
62import static org.junit.Assert.*;
63import static org.onlab.onos.net.Device.Type.SWITCH;
64import static org.onlab.onos.net.DeviceId.deviceId;
65import static org.onlab.onos.net.device.DeviceEvent.Type.*;
66
67/**
68 * Test codifying the device service & device provider service contracts.
69 */
tom41a2c5f2014-09-19 09:20:35 -070070public class DeviceManagerTest {
tome5ec3fd2014-09-04 15:18:06 -070071
tom7e02cda2014-09-18 12:05:46 -070072 private static final ProviderId PID = new ProviderId("of", "foo");
tome5ec3fd2014-09-04 15:18:06 -070073 private static final DeviceId DID1 = deviceId("of:foo");
74 private static final DeviceId DID2 = deviceId("of:bar");
75 private static final String MFR = "whitebox";
76 private static final String HW = "1.1.x";
77 private static final String SW1 = "3.8.1";
78 private static final String SW2 = "3.9.5";
79 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -070080 private static final ChassisId CID = new ChassisId();
tome5ec3fd2014-09-04 15:18:06 -070081
tom24c55cd2014-09-06 10:47:25 -070082 private static final PortNumber P1 = PortNumber.portNumber(1);
83 private static final PortNumber P2 = PortNumber.portNumber(2);
84 private static final PortNumber P3 = PortNumber.portNumber(3);
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -070085 private static final NodeId NID_LOCAL = new NodeId("local");
Pavlin Radoslavov444b5192014-10-28 10:45:19 -070086 private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
tom24c55cd2014-09-06 10:47:25 -070087
tom41a2c5f2014-09-19 09:20:35 -070088 private DeviceManager mgr;
tome5ec3fd2014-09-04 15:18:06 -070089
90 protected DeviceService service;
91 protected DeviceAdminService admin;
92 protected DeviceProviderRegistry registry;
93 protected DeviceProviderService providerService;
94 protected TestProvider provider;
95 protected TestListener listener = new TestListener();
96
97 @Before
98 public void setUp() {
tom41a2c5f2014-09-19 09:20:35 -070099 mgr = new DeviceManager();
tome5ec3fd2014-09-04 15:18:06 -0700100 service = mgr;
101 admin = mgr;
102 registry = mgr;
tom41a2c5f2014-09-19 09:20:35 -0700103 mgr.store = new SimpleDeviceStore();
tome5ec3fd2014-09-04 15:18:06 -0700104 mgr.eventDispatcher = new TestEventDispatcher();
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700105 mgr.mastershipService = new TestMastershipService();
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700106 mgr.clusterService = new TestClusterService();
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700107 mgr.deviceClockProviderService = new TestClockProviderService();
tome5ec3fd2014-09-04 15:18:06 -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
127 private void connectDevice(DeviceId deviceId, String swVersion) {
128 DeviceDescription description =
129 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700130 HW, swVersion, SN, CID);
tome5ec3fd2014-09-04 15:18:06 -0700131 providerService.deviceConnected(deviceId, description);
132 assertNotNull("device should be found", service.getDevice(DID1));
133 }
134
135 @Test
136 public void deviceConnected() {
137 assertNull("device should not be found", service.getDevice(DID1));
138 connectDevice(DID1, SW1);
139 validateEvents(DEVICE_ADDED);
140
141 Iterator<Device> it = service.getDevices().iterator();
142 assertNotNull("one device expected", it.next());
143 assertFalse("only one device expected", it.hasNext());
tomad2d2092014-09-06 23:24:20 -0700144 assertEquals("incorrect device count", 1, service.getDeviceCount());
tomff7eb7c2014-09-08 12:49:03 -0700145 assertTrue("device should be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700146 }
147
148 @Test
149 public void deviceDisconnected() {
150 connectDevice(DID1, SW1);
151 connectDevice(DID2, SW1);
152 validateEvents(DEVICE_ADDED, DEVICE_ADDED);
tomff7eb7c2014-09-08 12:49:03 -0700153 assertTrue("device should be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700154
155 // Disconnect
156 providerService.deviceDisconnected(DID1);
157 assertNotNull("device should not be found", service.getDevice(DID1));
tomff7eb7c2014-09-08 12:49:03 -0700158 assertFalse("device should not be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700159 validateEvents(DEVICE_AVAILABILITY_CHANGED);
160
161 // Reconnect
162 connectDevice(DID1, SW1);
163 validateEvents(DEVICE_AVAILABILITY_CHANGED);
tomad2d2092014-09-06 23:24:20 -0700164
165 assertEquals("incorrect device count", 2, service.getDeviceCount());
tome5ec3fd2014-09-04 15:18:06 -0700166 }
167
168 @Test
169 public void deviceUpdated() {
170 connectDevice(DID1, SW1);
171 validateEvents(DEVICE_ADDED);
172
173 connectDevice(DID1, SW2);
174 validateEvents(DEVICE_UPDATED);
175 }
176
177 @Test
178 public void getRole() {
179 connectDevice(DID1, SW1);
tom80c0e5e2014-09-08 18:08:58 -0700180 assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700181 }
182
tom24c55cd2014-09-06 10:47:25 -0700183 @Test
184 public void updatePorts() {
185 connectDevice(DID1, SW1);
186 List<PortDescription> pds = new ArrayList<>();
187 pds.add(new DefaultPortDescription(P1, true));
188 pds.add(new DefaultPortDescription(P2, true));
189 pds.add(new DefaultPortDescription(P3, true));
190 providerService.updatePorts(DID1, pds);
191 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED);
192 pds.clear();
tome5ec3fd2014-09-04 15:18:06 -0700193
tom24c55cd2014-09-06 10:47:25 -0700194 pds.add(new DefaultPortDescription(P1, false));
195 pds.add(new DefaultPortDescription(P3, true));
196 providerService.updatePorts(DID1, pds);
197 validateEvents(PORT_UPDATED, PORT_REMOVED);
198 }
199
200 @Test
201 public void updatePortStatus() {
202 connectDevice(DID1, SW1);
203 List<PortDescription> pds = new ArrayList<>();
204 pds.add(new DefaultPortDescription(P1, true));
205 pds.add(new DefaultPortDescription(P2, true));
206 providerService.updatePorts(DID1, pds);
207 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
208
209 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false));
210 validateEvents(PORT_UPDATED);
211 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false));
212 assertTrue("no events expected", listener.events.isEmpty());
213 }
214
215 @Test
216 public void getPorts() {
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 assertEquals("wrong port count", 2, service.getPorts(DID1).size());
224
225 Port port = service.getPort(DID1, P1);
226 assertEquals("incorrect port", P1, service.getPort(DID1, P1).number());
227 assertEquals("incorrect state", true, service.getPort(DID1, P1).isEnabled());
228 }
229
230 @Test
231 public void removeDevice() {
232 connectDevice(DID1, SW1);
233 connectDevice(DID2, SW2);
tomad2d2092014-09-06 23:24:20 -0700234 assertEquals("incorrect device count", 2, service.getDeviceCount());
tom24c55cd2014-09-06 10:47:25 -0700235 admin.removeDevice(DID1);
236 assertNull("device should not be found", service.getDevice(DID1));
237 assertNotNull("device should be found", service.getDevice(DID2));
tomad2d2092014-09-06 23:24:20 -0700238 assertEquals("incorrect device count", 1, service.getDeviceCount());
239
tom24c55cd2014-09-06 10:47:25 -0700240 }
tome5ec3fd2014-09-04 15:18:06 -0700241
242 protected void validateEvents(Enum... types) {
243 int i = 0;
244 assertEquals("wrong events received", types.length, listener.events.size());
245 for (Event event : listener.events) {
246 assertEquals("incorrect event type", types[i], event.type());
247 i++;
248 }
249 listener.events.clear();
250 }
251
252
253 private class TestProvider extends AbstractProvider implements DeviceProvider {
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700254 private DeviceId deviceReceived;
tome5ec3fd2014-09-04 15:18:06 -0700255 private MastershipRole roleReceived;
256
257 public TestProvider() {
258 super(PID);
259 }
260
261 @Override
262 public void triggerProbe(Device device) {
263 }
264
265 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700266 public void roleChanged(DeviceId device, MastershipRole newRole) {
tome5ec3fd2014-09-04 15:18:06 -0700267 deviceReceived = device;
268 roleReceived = newRole;
269 }
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700270
271 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700272 public boolean isReachable(DeviceId device) {
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700273 return false;
274 }
tome5ec3fd2014-09-04 15:18:06 -0700275 }
276
277 private static class TestListener implements DeviceListener {
278 final List<DeviceEvent> events = new ArrayList<>();
279
280 @Override
281 public void event(DeviceEvent event) {
282 events.add(event);
283 }
284 }
285
Ayaka Koshibec4047702014-10-07 14:43:52 -0700286 private static class TestMastershipService
287 extends MastershipServiceAdapter {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700288 @Override
tomb41d1ac2014-09-24 01:51:24 -0700289 public MastershipRole getLocalRole(DeviceId deviceId) {
290 return MastershipRole.MASTER;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700291 }
292
293 @Override
294 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
295 return Sets.newHashSet(DID1, DID2);
296 }
297
298 @Override
299 public MastershipRole requestRoleFor(DeviceId deviceId) {
300 return MastershipRole.MASTER;
301 }
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700302
303 @Override
304 public MastershipTermService requestTermService() {
305 return new MastershipTermService() {
306 @Override
307 public MastershipTerm getMastershipTerm(DeviceId deviceId) {
308 // FIXME: just returning something not null
309 return MastershipTerm.of(NID_LOCAL, 1);
310 }
311 };
312 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700313 }
314
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700315 // code clone
316 private final class TestClusterService implements ClusterService {
317
318 ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);
319
320 @Override
321 public ControllerNode getLocalNode() {
322 return local;
323 }
324
325 @Override
326 public Set<ControllerNode> getNodes() {
327 return null;
328 }
329
330 @Override
331 public ControllerNode getNode(NodeId nodeId) {
332 return null;
333 }
334
335 @Override
336 public State getState(NodeId nodeId) {
337 return null;
338 }
339
340 @Override
341 public void addListener(ClusterEventListener listener) {
342 }
343
344 @Override
345 public void removeListener(ClusterEventListener listener) {
346 }
347 }
348
349 private final class TestClockProviderService implements
Yuta HIGUCHI093e83e2014-10-10 22:26:11 -0700350 DeviceClockProviderService {
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700351
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700352 private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet();
353
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700354 @Override
355 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700356 registerdBefore.add(deviceId);
357 }
358
359 @Override
360 public boolean isTimestampAvailable(DeviceId deviceId) {
361 return registerdBefore.contains(deviceId);
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700362 }
363 }
tome5ec3fd2014-09-04 15:18:06 -0700364}