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