2  * Copyright 2015 Open Networking Laboratory
 
   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
 
   8  *     http://www.apache.org/licenses/LICENSE-2.0
 
  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.
 
  16 package org.onosproject.openflow.controller.impl;
 
  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;
 
  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;
 
  43 import com.google.common.collect.ImmutableSet;
 
  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;
 
  57  * Unit tests for the open flow controller implementation test.
 
  59 public class OpenFlowControllerImplTest {
 
  61     OpenFlowSwitch switch1;
 
  63     OpenFlowSwitch switch2;
 
  65     OpenFlowSwitch switch3;
 
  68     OpenFlowControllerImpl controller;
 
  69     OpenFlowControllerImpl.OpenFlowSwitchAgent agent;
 
  70     TestSwitchListener switchListener;
 
  73      * Test harness for a switch listener.
 
  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<>();
 
  81         public void switchAdded(Dpid dpid) {
 
  86         public void switchRemoved(Dpid dpid) {
 
  87             removedDpids.add(dpid);
 
  91         public void switchChanged(Dpid dpid) {
 
  92             changedDpids.add(dpid);
 
  96         public void portChanged(Dpid dpid, OFPortStatus status) {
 
 101         public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
 
 108      * Sets up switches to use as data, mocks and launches a controller instance.
 
 111     public void setUp() {
 
 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) {
 
 124         controller = new OpenFlowControllerImpl();
 
 125         agent = controller.agent;
 
 127         switchListener = new TestSwitchListener();
 
 128         controller.addListener(switchListener);
 
 130         ComponentConfigService mockConfigService =
 
 131                 EasyMock.createMock(ComponentConfigService.class);
 
 132         expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
 
 133         mockConfigService.registerProperties(controller.getClass());
 
 135         mockConfigService.unregisterProperties(controller.getClass(), false);
 
 137         expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
 
 138         controller.cfgService = mockConfigService;
 
 139         replay(mockConfigService);
 
 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);
 
 147         controller.activate(mockContext);
 
 151     public void tearDown() {
 
 152         controller.removeListener(switchListener);
 
 153         controller.deactivate();
 
 157      * Converts an Iterable of some type into a stream of that type.
 
 159      * @param items Iterable of objects
 
 160      * @param <T> type of the items in the iterable
 
 161      * @return stream of objects of type T
 
 163     private <T> Stream<T> makeIntoStream(Iterable<T> items) {
 
 164         return StreamSupport.stream(
 
 165                 Spliterators.spliteratorUnknownSize(
 
 166                         items.iterator(), Spliterator.ORDERED), false);
 
 171      * Tests adding and removing connected switches.
 
 174     public void testAddRemoveConnectedSwitch() {
 
 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));
 
 184         // Make sure the listener add callbacks fired
 
 185         assertThat(switchListener.addedDpids, hasSize(3));
 
 186         assertThat(switchListener.addedDpids, hasItems(dpid1, dpid2, dpid3));
 
 188         // Test adding a switch twice - it should fail
 
 189         boolean addBadSwitch1 = agent.addConnectedSwitch(dpid1, switch1);
 
 190         assertThat(addBadSwitch1, is(false));
 
 192         assertThat(controller.connectedSwitches.size(), is(3));
 
 194         // test querying the switch list
 
 195         Stream<OpenFlowSwitch> fetchedSwitches =
 
 196                 makeIntoStream(controller.getSwitches());
 
 197         long switchCount = fetchedSwitches.count();
 
 198         assertThat(switchCount, is(3L));
 
 200         // test querying the individual switch
 
 201         OpenFlowSwitch queriedSwitch = controller.getSwitch(dpid1);
 
 202         assertThat(queriedSwitch, is(switch1));
 
 205         agent.removeConnectedSwitch(dpid3);
 
 206         Stream<OpenFlowSwitch> fetchedSwitchesAfterRemove =
 
 207                 makeIntoStream(controller.getSwitches());
 
 208         long switchCountAfterRemove = fetchedSwitchesAfterRemove.count();
 
 209         assertThat(switchCountAfterRemove, is(2L));
 
 211         // Make sure the listener delete callbacks fired
 
 212         assertThat(switchListener.removedDpids, hasSize(1));
 
 213         assertThat(switchListener.removedDpids, hasItems(dpid3));
 
 215         // test querying the removed switch
 
 216         OpenFlowSwitch queriedSwitchAfterRemove = controller.getSwitch(dpid3);
 
 217         assertThat(queriedSwitchAfterRemove, nullValue());
 
 221      * Tests adding master switches.
 
 224     public void testMasterSwitch() {
 
 225         agent.addConnectedSwitch(dpid1, switch1);
 
 226         agent.transitionToMasterSwitch(dpid1);
 
 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));
 
 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));
 
 245      * Tests adding equal switches.
 
 248     public void testEqualSwitch() {
 
 249         agent.addConnectedSwitch(dpid1, switch1);
 
 250         agent.transitionToEqualSwitch(dpid1);
 
 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));
 
 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));
 
 269      * Tests changing switch role.
 
 272     public void testRoleSetting() {
 
 273         agent.addConnectedSwitch(dpid2, switch2);
 
 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));
 
 280         // check that changing state on an unconnected switch does not crash
 
 281         controller.setRole(dpid3, RoleState.SLAVE);