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