blob: 8aa53ef4962326e081db2ab8a0b74aa2655e7dfc [file] [log] [blame]
Ray Milkeyca20bb52015-11-10 13:59:16 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Ray Milkeyca20bb52015-11-10 13:59:16 -08003 *
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 */
16package org.onosproject.openflow.controller.impl;
17
18import java.net.URI;
19import java.net.URISyntaxException;
20import java.util.ArrayList;
21import java.util.Dictionary;
22import java.util.Hashtable;
23import java.util.List;
24import java.util.Spliterator;
25import java.util.Spliterators;
26import java.util.stream.Stream;
27import java.util.stream.StreamSupport;
28
29import org.easymock.EasyMock;
30import org.junit.After;
31import org.junit.Before;
32import org.junit.Test;
33import org.onlab.junit.TestTools;
34import org.onosproject.cfg.ComponentConfigService;
Charles Chanecfdfb72015-11-24 19:05:50 -080035import org.onosproject.core.CoreService;
Yuta HIGUCHIcedd0df2016-08-23 11:44:13 -070036import org.onosproject.net.device.DeviceServiceAdapter;
Ray Milkeyca20bb52015-11-10 13:59:16 -080037import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
38import org.onosproject.openflow.controller.Dpid;
39import org.onosproject.openflow.controller.OpenFlowSwitch;
40import org.onosproject.openflow.controller.OpenFlowSwitchListener;
41import org.onosproject.openflow.controller.RoleState;
42import org.osgi.service.component.ComponentContext;
43import org.projectfloodlight.openflow.protocol.OFPortStatus;
44
45import com.google.common.collect.ImmutableSet;
46
47import static junit.framework.TestCase.fail;
48import static org.easymock.EasyMock.anyObject;
49import static org.easymock.EasyMock.expect;
50import static org.easymock.EasyMock.expectLastCall;
51import static org.easymock.EasyMock.replay;
52import static org.hamcrest.MatcherAssert.assertThat;
53import static org.hamcrest.Matchers.hasItems;
54import static org.hamcrest.Matchers.hasSize;
55import static org.hamcrest.Matchers.is;
56import static org.hamcrest.Matchers.nullValue;
57
58/**
59 * Unit tests for the open flow controller implementation test.
60 */
61public class OpenFlowControllerImplTest {
62
63 OpenFlowSwitch switch1;
64 Dpid dpid1;
65 OpenFlowSwitch switch2;
66 Dpid dpid2;
67 OpenFlowSwitch switch3;
68 Dpid dpid3;
69
70 OpenFlowControllerImpl controller;
71 OpenFlowControllerImpl.OpenFlowSwitchAgent agent;
72 TestSwitchListener switchListener;
73
74 /**
75 * Test harness for a switch listener.
76 */
77 static class TestSwitchListener implements OpenFlowSwitchListener {
78 final List<Dpid> removedDpids = new ArrayList<>();
79 final List<Dpid> addedDpids = new ArrayList<>();
80 final List<Dpid> changedDpids = new ArrayList<>();
81
82 @Override
83 public void switchAdded(Dpid dpid) {
84 addedDpids.add(dpid);
85 }
86
87 @Override
88 public void switchRemoved(Dpid dpid) {
89 removedDpids.add(dpid);
90 }
91
92 @Override
93 public void switchChanged(Dpid dpid) {
94 changedDpids.add(dpid);
95 }
96
97 @Override
98 public void portChanged(Dpid dpid, OFPortStatus status) {
99 // Stub
100 }
101
102 @Override
103 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
104 // Stub
105 }
106 }
107
108
109 /**
110 * Sets up switches to use as data, mocks and launches a controller instance.
111 */
112 @Before
113 public void setUp() {
114 try {
115 switch1 = new OpenflowSwitchDriverAdapter();
116 dpid1 = Dpid.dpid(new URI("of:0000000000000111"));
117 switch2 = new OpenflowSwitchDriverAdapter();
118 dpid2 = Dpid.dpid(new URI("of:0000000000000222"));
119 switch3 = new OpenflowSwitchDriverAdapter();
120 dpid3 = Dpid.dpid(new URI("of:0000000000000333"));
121 } catch (URISyntaxException ex) {
122 // Does not happen
123 fail();
124 }
125
126 controller = new OpenFlowControllerImpl();
127 agent = controller.agent;
128
129 switchListener = new TestSwitchListener();
130 controller.addListener(switchListener);
131
Charles Chanecfdfb72015-11-24 19:05:50 -0800132 CoreService mockCoreService =
133 EasyMock.createMock(CoreService.class);
134 controller.coreService = mockCoreService;
135
Ray Milkeyca20bb52015-11-10 13:59:16 -0800136 ComponentConfigService mockConfigService =
137 EasyMock.createMock(ComponentConfigService.class);
138 expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
139 mockConfigService.registerProperties(controller.getClass());
140 expectLastCall();
141 mockConfigService.unregisterProperties(controller.getClass(), false);
142 expectLastCall();
143 expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
144 controller.cfgService = mockConfigService;
145 replay(mockConfigService);
146
Yuta HIGUCHIcedd0df2016-08-23 11:44:13 -0700147 controller.deviceService = new DeviceServiceAdapter();
148
Ray Milkeyca20bb52015-11-10 13:59:16 -0800149 ComponentContext mockContext = EasyMock.createMock(ComponentContext.class);
Ray Milkeyf80bbb22016-03-11 10:16:22 -0800150 Dictionary<String, Object> properties = new Hashtable<>();
Ray Milkeyca20bb52015-11-10 13:59:16 -0800151 properties.put("openflowPorts",
152 Integer.toString(TestTools.findAvailablePort(0)));
153 expect(mockContext.getProperties()).andReturn(properties);
154 replay(mockContext);
155 controller.activate(mockContext);
156 }
157
158 @After
159 public void tearDown() {
160 controller.removeListener(switchListener);
161 controller.deactivate();
162 }
163
164 /**
165 * Converts an Iterable of some type into a stream of that type.
166 *
167 * @param items Iterable of objects
168 * @param <T> type of the items in the iterable
169 * @return stream of objects of type T
170 */
171 private <T> Stream<T> makeIntoStream(Iterable<T> items) {
172 return StreamSupport.stream(
173 Spliterators.spliteratorUnknownSize(
174 items.iterator(), Spliterator.ORDERED), false);
175 }
176
177
178 /**
179 * Tests adding and removing connected switches.
180 */
181 @Test
182 public void testAddRemoveConnectedSwitch() {
183
184 // test adding connected switches
185 boolean addSwitch1 = agent.addConnectedSwitch(dpid1, switch1);
186 assertThat(addSwitch1, is(true));
187 boolean addSwitch2 = agent.addConnectedSwitch(dpid2, switch2);
188 assertThat(addSwitch2, is(true));
189 boolean addSwitch3 = agent.addConnectedSwitch(dpid3, switch3);
190 assertThat(addSwitch3, is(true));
191
192 // Make sure the listener add callbacks fired
193 assertThat(switchListener.addedDpids, hasSize(3));
194 assertThat(switchListener.addedDpids, hasItems(dpid1, dpid2, dpid3));
195
196 // Test adding a switch twice - it should fail
197 boolean addBadSwitch1 = agent.addConnectedSwitch(dpid1, switch1);
198 assertThat(addBadSwitch1, is(false));
199
200 assertThat(controller.connectedSwitches.size(), is(3));
201
202 // test querying the switch list
203 Stream<OpenFlowSwitch> fetchedSwitches =
204 makeIntoStream(controller.getSwitches());
205 long switchCount = fetchedSwitches.count();
206 assertThat(switchCount, is(3L));
207
208 // test querying the individual switch
209 OpenFlowSwitch queriedSwitch = controller.getSwitch(dpid1);
210 assertThat(queriedSwitch, is(switch1));
211
212 // Remove a switch
213 agent.removeConnectedSwitch(dpid3);
214 Stream<OpenFlowSwitch> fetchedSwitchesAfterRemove =
215 makeIntoStream(controller.getSwitches());
216 long switchCountAfterRemove = fetchedSwitchesAfterRemove.count();
217 assertThat(switchCountAfterRemove, is(2L));
218
219 // Make sure the listener delete callbacks fired
220 assertThat(switchListener.removedDpids, hasSize(1));
221 assertThat(switchListener.removedDpids, hasItems(dpid3));
222
223 // test querying the removed switch
224 OpenFlowSwitch queriedSwitchAfterRemove = controller.getSwitch(dpid3);
225 assertThat(queriedSwitchAfterRemove, nullValue());
226 }
227
228 /**
229 * Tests adding master switches.
230 */
231 @Test
232 public void testMasterSwitch() {
233 agent.addConnectedSwitch(dpid1, switch1);
234 agent.transitionToMasterSwitch(dpid1);
235
236 Stream<OpenFlowSwitch> fetchedMasterSwitches =
237 makeIntoStream(controller.getMasterSwitches());
238 assertThat(fetchedMasterSwitches.count(), is(1L));
239 Stream<OpenFlowSwitch> fetchedActivatedSwitches =
240 makeIntoStream(controller.getEqualSwitches());
241 assertThat(fetchedActivatedSwitches.count(), is(0L));
242 OpenFlowSwitch fetchedSwitch1 = controller.getMasterSwitch(dpid1);
243 assertThat(fetchedSwitch1, is(switch1));
244
245 agent.addConnectedSwitch(dpid2, switch2);
246 boolean addSwitch2 = agent.addActivatedMasterSwitch(dpid2, switch2);
247 assertThat(addSwitch2, is(true));
248 OpenFlowSwitch fetchedSwitch2 = controller.getMasterSwitch(dpid2);
249 assertThat(fetchedSwitch2, is(switch2));
250 }
251
252 /**
253 * Tests adding equal switches.
254 */
255 @Test
256 public void testEqualSwitch() {
257 agent.addConnectedSwitch(dpid1, switch1);
258 agent.transitionToEqualSwitch(dpid1);
259
260 Stream<OpenFlowSwitch> fetchedEqualSwitches =
261 makeIntoStream(controller.getEqualSwitches());
262 assertThat(fetchedEqualSwitches.count(), is(1L));
263 Stream<OpenFlowSwitch> fetchedActivatedSwitches =
264 makeIntoStream(controller.getMasterSwitches());
265 assertThat(fetchedActivatedSwitches.count(), is(0L));
266 OpenFlowSwitch fetchedSwitch1 = controller.getEqualSwitch(dpid1);
267 assertThat(fetchedSwitch1, is(switch1));
268
269 agent.addConnectedSwitch(dpid2, switch2);
270 boolean addSwitch2 = agent.addActivatedEqualSwitch(dpid2, switch2);
271 assertThat(addSwitch2, is(true));
272 OpenFlowSwitch fetchedSwitch2 = controller.getEqualSwitch(dpid2);
273 assertThat(fetchedSwitch2, is(switch2));
274 }
275
276 /**
277 * Tests changing switch role.
278 */
279 @Test
280 public void testRoleSetting() {
281 agent.addConnectedSwitch(dpid2, switch2);
282
283 // check that state can be changed for a connected switch
284 assertThat(switch2.getRole(), is(RoleState.MASTER));
285 controller.setRole(dpid2, RoleState.EQUAL);
286 assertThat(switch2.getRole(), is(RoleState.EQUAL));
287
288 // check that changing state on an unconnected switch does not crash
289 controller.setRole(dpid3, RoleState.SLAVE);
290 }
291}