Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1 | /** |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 2 | * Copyright 2011, Big Switch Networks, Inc. |
| 3 | * Originally created by David Erickson, Stanford University |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 6 | * not use this file except in compliance with the License. You may obtain |
| 7 | * a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 14 | * License for the specific language governing permissions and limitations |
| 15 | * under the License. |
| 16 | **/ |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 17 | |
| 18 | package net.floodlightcontroller.core.internal; |
| 19 | |
HIGUCHI Yuta | 5968f72 | 2013-06-12 10:58:50 -0700 | [diff] [blame] | 20 | import static org.easymock.EasyMock.anyObject; |
HIGUCHI Yuta | 5968f72 | 2013-06-12 10:58:50 -0700 | [diff] [blame] | 21 | import static org.easymock.EasyMock.createMock; |
| 22 | import static org.easymock.EasyMock.createNiceMock; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 23 | import static org.easymock.EasyMock.createStrictMock; |
HIGUCHI Yuta | 5968f72 | 2013-06-12 10:58:50 -0700 | [diff] [blame] | 24 | import static org.easymock.EasyMock.eq; |
| 25 | import static org.easymock.EasyMock.expect; |
| 26 | import static org.easymock.EasyMock.expectLastCall; |
| 27 | import static org.easymock.EasyMock.isA; |
| 28 | import static org.easymock.EasyMock.replay; |
| 29 | import static org.easymock.EasyMock.reset; |
| 30 | import static org.easymock.EasyMock.same; |
| 31 | import static org.easymock.EasyMock.verify; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 32 | import static org.junit.Assert.assertArrayEquals; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 33 | |
| 34 | import java.util.ArrayList; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 35 | import java.util.HashSet; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 36 | import java.util.List; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 37 | import java.util.Set; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 38 | import java.util.concurrent.Future; |
| 39 | import java.util.concurrent.TimeUnit; |
| 40 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 41 | import net.floodlightcontroller.core.FloodlightContext; |
HIGUCHI Yuta | 5968f72 | 2013-06-12 10:58:50 -0700 | [diff] [blame] | 42 | import net.floodlightcontroller.core.FloodlightProvider; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 43 | import net.floodlightcontroller.core.IFloodlightProviderService; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 44 | import net.floodlightcontroller.core.IFloodlightProviderService.Role; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 45 | import net.floodlightcontroller.core.IListener; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 46 | import net.floodlightcontroller.core.IListener.Command; |
HIGUCHI Yuta | 5968f72 | 2013-06-12 10:58:50 -0700 | [diff] [blame] | 47 | import net.floodlightcontroller.core.IOFMessageListener; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 48 | import net.floodlightcontroller.core.IOFSwitch; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 49 | import net.floodlightcontroller.core.IOFSwitch.PortChangeType; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 50 | import net.floodlightcontroller.core.IOFSwitchListener; |
Pankaj Berde | 6e42173 | 2013-08-14 15:17:52 -0700 | [diff] [blame] | 51 | import net.floodlightcontroller.core.IUpdate; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 52 | import net.floodlightcontroller.core.internal.Controller.SwitchUpdate; |
| 53 | import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 54 | import net.floodlightcontroller.core.module.FloodlightModuleContext; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 55 | import net.floodlightcontroller.core.test.MockThreadPoolService; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 56 | import net.floodlightcontroller.debugcounter.DebugCounter; |
| 57 | import net.floodlightcontroller.debugcounter.IDebugCounterService; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 58 | import net.floodlightcontroller.restserver.IRestApiService; |
| 59 | import net.floodlightcontroller.restserver.RestApiServer; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 60 | import net.floodlightcontroller.test.FloodlightTestCase; |
| 61 | import net.floodlightcontroller.threadpool.IThreadPoolService; |
Jonathan Hart | 23701d1 | 2014-04-03 10:45:48 -0700 | [diff] [blame] | 62 | import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService; |
Jonathan Hart | 284e70f | 2014-07-05 12:32:51 -0700 | [diff] [blame] | 63 | import net.onrc.onos.core.linkdiscovery.LinkDiscoveryManager; |
Jonathan Hart | deda0ba | 2014-04-03 11:14:12 -0700 | [diff] [blame] | 64 | import net.onrc.onos.core.packet.ARP; |
| 65 | import net.onrc.onos.core.packet.Ethernet; |
| 66 | import net.onrc.onos.core.packet.IPacket; |
| 67 | import net.onrc.onos.core.packet.IPv4; |
| 68 | import net.onrc.onos.core.registry.IControllerRegistryService; |
| 69 | import net.onrc.onos.core.registry.StandaloneRegistry; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 70 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 71 | import org.junit.Before; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 72 | import org.junit.Test; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 73 | import org.projectfloodlight.openflow.protocol.OFDescStatsReply; |
| 74 | import org.projectfloodlight.openflow.protocol.OFFactories; |
| 75 | import org.projectfloodlight.openflow.protocol.OFFactory; |
| 76 | import org.projectfloodlight.openflow.protocol.OFFeaturesReply; |
| 77 | import org.projectfloodlight.openflow.protocol.OFFlowMod; |
| 78 | import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; |
| 79 | import org.projectfloodlight.openflow.protocol.OFPacketIn; |
| 80 | import org.projectfloodlight.openflow.protocol.OFPacketInReason; |
| 81 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
| 82 | import org.projectfloodlight.openflow.protocol.OFPortState; |
| 83 | import org.projectfloodlight.openflow.protocol.OFStatsReply; |
| 84 | import org.projectfloodlight.openflow.protocol.OFType; |
| 85 | import org.projectfloodlight.openflow.protocol.OFVersion; |
| 86 | import org.projectfloodlight.openflow.protocol.ver10.OFStatsReplyFlagsSerializerVer10; |
| 87 | import org.projectfloodlight.openflow.types.DatapathId; |
| 88 | import org.projectfloodlight.openflow.types.OFBufferId; |
| 89 | import org.projectfloodlight.openflow.types.OFPort; |
| 90 | import org.projectfloodlight.openflow.util.HexString; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 91 | |
| 92 | /** |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 93 | * @author David Erickson (daviderickson@cs.stanford.edu) |
| 94 | */ |
| 95 | public class ControllerTest extends FloodlightTestCase { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 96 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 97 | private Controller controller; |
| 98 | private MockThreadPoolService tp; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 99 | protected OFFactory factory10 = OFFactories.getFactory(OFVersion.OF_10); |
| 100 | private IPacket testPacket; |
| 101 | private OFPacketIn pi; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 102 | |
| 103 | @Override |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 104 | @Before |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 105 | public void setUp() throws Exception { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 106 | doSetUp(Role.MASTER); |
| 107 | } |
| 108 | |
| 109 | public void doSetUp(Role role) throws Exception { |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 110 | super.setUp(); |
| 111 | FloodlightModuleContext fmc = new FloodlightModuleContext(); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 112 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 113 | FloodlightProvider cm = new FloodlightProvider(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 114 | |
| 115 | controller = (Controller) cm.getServiceImpls().get( |
| 116 | IFloodlightProviderService.class); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 117 | fmc.addService(IFloodlightProviderService.class, controller); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 118 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 119 | RestApiServer restApi = new RestApiServer(); |
| 120 | fmc.addService(IRestApiService.class, restApi); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 121 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 122 | // TODO replace with mock if further testing is needed. |
| 123 | DebugCounter counterService = new DebugCounter(); |
| 124 | fmc.addService(IDebugCounterService.class, counterService); |
| 125 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 126 | tp = new MockThreadPoolService(); |
| 127 | fmc.addService(IThreadPoolService.class, tp); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 128 | |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 129 | // Following added by ONOS |
| 130 | // TODO replace with mock if further testing is needed. |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 131 | StandaloneRegistry sr = new StandaloneRegistry(); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 132 | fmc.addService(IControllerRegistryService.class, sr); |
Jonathan Hart | 220b829 | 2013-12-07 19:25:11 -0800 | [diff] [blame] | 133 | LinkDiscoveryManager linkDiscovery = new LinkDiscoveryManager(); |
| 134 | fmc.addService(ILinkDiscoveryService.class, linkDiscovery); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 135 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 136 | restApi.init(fmc); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 137 | cm.init(fmc); |
| 138 | tp.init(fmc); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 139 | sr.init(fmc); |
Jonathan Hart | 220b829 | 2013-12-07 19:25:11 -0800 | [diff] [blame] | 140 | linkDiscovery.init(fmc); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 141 | restApi.startUp(fmc); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 142 | cm.startUp(fmc); |
| 143 | tp.startUp(fmc); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 144 | sr.startUp(fmc); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 145 | // linkDiscovery.startUp(fmc); |
| 146 | |
| 147 | testPacket = new Ethernet() |
| 148 | .setSourceMACAddress("00:44:33:22:11:00") |
| 149 | .setDestinationMACAddress("00:11:22:33:44:55") |
| 150 | .setEtherType(Ethernet.TYPE_ARP) |
| 151 | .setPayload( |
| 152 | new ARP() |
| 153 | .setHardwareType(ARP.HW_TYPE_ETHERNET) |
| 154 | .setProtocolType(ARP.PROTO_TYPE_IP) |
| 155 | .setHardwareAddressLength((byte) 6) |
| 156 | .setProtocolAddressLength((byte) 4) |
| 157 | .setOpCode(ARP.OP_REPLY) |
| 158 | .setSenderHardwareAddress( |
| 159 | Ethernet.toMACAddress("00:44:33:22:11:00")) |
| 160 | .setSenderProtocolAddress( |
| 161 | IPv4.toIPv4AddressBytes("192.168.1.1")) |
| 162 | .setTargetHardwareAddress( |
| 163 | Ethernet.toMACAddress("00:11:22:33:44:55")) |
| 164 | .setTargetProtocolAddress( |
| 165 | IPv4.toIPv4AddressBytes("192.168.1.2"))); |
| 166 | byte[] testPacketSerialized = testPacket.serialize(); |
| 167 | |
| 168 | pi = factory10.buildPacketIn() |
| 169 | .setBufferId(OFBufferId.NO_BUFFER) |
| 170 | .setInPort(OFPort.of(1)) |
| 171 | .setData(testPacketSerialized) |
| 172 | .setReason(OFPacketInReason.NO_MATCH) |
| 173 | .setTotalLen((short) testPacketSerialized.length).build(); |
| 174 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | public Controller getController() { |
| 178 | return controller; |
| 179 | } |
| 180 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 181 | protected OFStatsReply getStatisticsReply(int transactionId, |
| 182 | int count, boolean moreReplies) { |
| 183 | List<OFFlowStatsEntry> statistics = new ArrayList<OFFlowStatsEntry>(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 184 | for (int i = 0; i < count; ++i) { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 185 | statistics.add(factory10.buildFlowStatsEntry().build()); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 186 | } |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 187 | assertEquals(statistics.size(), count); |
| 188 | OFStatsReply sr; |
| 189 | if (moreReplies) { |
| 190 | sr = (factory10.buildFlowStatsReply() |
| 191 | .setXid(transactionId) |
| 192 | .setEntries(statistics) |
| 193 | .setFlags(OFStatsReplyFlagsSerializerVer10.ofWireValue((short) 1)) |
| 194 | .build()); |
| 195 | } |
| 196 | else { |
| 197 | sr = (factory10.buildFlowStatsReply() |
| 198 | .setXid(transactionId) |
| 199 | .setEntries(statistics).build()); |
| 200 | } |
| 201 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 202 | return sr; |
| 203 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 204 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 205 | private OFDescStatsReply createOFDescStatsReply() { |
| 206 | OFDescStatsReply desc = factory10.buildDescStatsReply() |
| 207 | .setHwDesc("") |
| 208 | .setMfrDesc("") |
| 209 | .setDpDesc("") |
| 210 | .setMfrDesc("") |
| 211 | .setSwDesc("") |
| 212 | .setSerialNum("").build(); |
| 213 | return desc; |
| 214 | } |
| 215 | |
| 216 | private OFFeaturesReply createOFFeaturesReply() { |
| 217 | OFFeaturesReply fr = factory10.buildFeaturesReply() |
| 218 | .setPorts(new ArrayList<OFPortDesc>()) |
| 219 | .build(); |
| 220 | return fr; |
| 221 | |
| 222 | } |
| 223 | |
| 224 | /** |
| 225 | * Set the mock expectations for sw when sw is passed to addSwitch The same |
| 226 | * expectations can be used when a new SwitchSyncRepresentation is created |
| 227 | * from the given mocked switch |
| 228 | */ |
| 229 | protected void setupSwitchForAddSwitch(IOFSwitch sw, long dpid, |
| 230 | OFDescStatsReply desc, OFFeaturesReply featuresReply) { |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 231 | String dpidString = HexString.toHexString(dpid); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 232 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 233 | if (desc == null) { |
| 234 | desc = createOFDescStatsReply(); |
| 235 | } |
| 236 | if (featuresReply == null) { |
| 237 | featuresReply = createOFFeaturesReply(); |
| 238 | featuresReply.createBuilder().setDatapathId(DatapathId.of(dpid)); |
| 239 | |
| 240 | } |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 241 | expect(sw.getId()).andReturn(dpid).anyTimes(); |
| 242 | expect(sw.getStringId()).andReturn(dpidString).anyTimes(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 243 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 244 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 245 | /** |
| 246 | * Run the controller's main loop so that updates are processed |
| 247 | */ |
| 248 | protected class ControllerRunThread extends Thread { |
Yuta HIGUCHI | 0b7c19e | 2014-07-21 23:33:20 -0700 | [diff] [blame] | 249 | @Override |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 250 | public void run() { |
| 251 | controller.openFlowPort = 0; // Don't listen |
| 252 | controller.run(); |
| 253 | } |
| 254 | } |
| 255 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 256 | @SuppressWarnings("unchecked") |
| 257 | private <T> void setupListenerOrdering(IListener<T> listener) { |
| 258 | listener.isCallbackOrderingPostreq((T) anyObject(), |
| 259 | anyObject(String.class)); |
| 260 | expectLastCall().andReturn(false).anyTimes(); |
| 261 | |
| 262 | listener.isCallbackOrderingPrereq((T) anyObject(), |
| 263 | anyObject(String.class)); |
| 264 | expectLastCall().andReturn(false).anyTimes(); |
| 265 | } |
| 266 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 267 | /** |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 268 | * Verify that a listener that throws an exception halts further execution, |
| 269 | * and verify that the Commands STOP and CONTINUE are honored. |
| 270 | * |
| 271 | * @throws Exception |
| 272 | */ |
| 273 | |
| 274 | @Test |
| 275 | public void testHandleMessagesNoListeners() throws Exception { |
| 276 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 277 | expect(sw.getId()).andReturn(0L).anyTimes(); |
| 278 | expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes(); |
| 279 | expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes(); |
| 280 | replay(sw); |
| 281 | controller.handleMessage(sw, pi, null); |
| 282 | verify(sw); |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Test message dispatching to OFMessageListeners. Test ordering of |
| 287 | * listeners for different types (we do this implicitly by using STOP and |
| 288 | * CONTINUE and making sure the processing stops at the right place) Verify |
| 289 | * that a listener that throws an exception halts further execution, and |
| 290 | * verify that the Commands STOP and CONTINUE are honored. |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 291 | * |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 292 | * @throws Exception |
| 293 | */ |
| 294 | @Test |
| 295 | public void testHandleMessages() throws Exception { |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 296 | controller.removeOFMessageListeners(OFType.PACKET_IN); |
| 297 | |
| 298 | IOFSwitch sw = createMock(IOFSwitch.class); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 299 | expect(sw.getId()).andReturn(0L).anyTimes(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 300 | expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 301 | expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes(); |
| 302 | // Setup listener orderings |
| 303 | IOFMessageListener test1 = createMock(IOFMessageListener.class); |
| 304 | expect(test1.getName()).andReturn("test1").anyTimes(); |
| 305 | setupListenerOrdering(test1); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 306 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 307 | IOFMessageListener test2 = createMock(IOFMessageListener.class); |
| 308 | expect(test2.getName()).andReturn("test2").anyTimes(); |
| 309 | // using a postreq and a prereq ordering here |
| 310 | expect(test2.isCallbackOrderingPrereq(OFType.PACKET_IN, "test1")) |
| 311 | .andReturn(true).atLeastOnce(); |
| 312 | expect(test2.isCallbackOrderingPostreq(OFType.FLOW_MOD, "test1")) |
| 313 | .andReturn(true).atLeastOnce(); |
| 314 | setupListenerOrdering(test2); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 315 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 316 | IOFMessageListener test3 = createMock(IOFMessageListener.class); |
| 317 | expect(test3.getName()).andReturn("test3").anyTimes(); |
| 318 | expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test1"))) |
| 319 | .andReturn(true).atLeastOnce(); |
| 320 | expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test2"))) |
| 321 | .andReturn(true).atLeastOnce(); |
| 322 | setupListenerOrdering(test3); |
| 323 | |
| 324 | // Ordering: PacketIn: test1 -> test2 -> test3 |
| 325 | // FlowMod: test2 -> test1 |
| 326 | replay(test1, test2, test3); |
| 327 | controller.addOFMessageListener(OFType.PACKET_IN, test1); |
| 328 | controller.addOFMessageListener(OFType.PACKET_IN, test3); |
| 329 | controller.addOFMessageListener(OFType.PACKET_IN, test2); |
| 330 | controller.addOFMessageListener(OFType.FLOW_MOD, test1); |
| 331 | controller.addOFMessageListener(OFType.FLOW_MOD, test2); |
| 332 | verify(test1); |
| 333 | verify(test2); |
| 334 | verify(test3); |
| 335 | |
| 336 | replay(sw); |
| 337 | |
| 338 | // ------------------ |
| 339 | // Test PacketIn handling: all listeners return CONTINUE |
| 340 | reset(test1, test2, test3); |
| 341 | expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 342 | .andReturn(Command.CONTINUE); |
| 343 | expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 344 | .andReturn(Command.CONTINUE); |
| 345 | expect(test3.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 346 | .andReturn(Command.CONTINUE); |
| 347 | replay(test1, test2, test3); |
| 348 | controller.handleMessage(sw, pi, null); |
| 349 | verify(test1); |
| 350 | verify(test2); |
| 351 | verify(test3); |
| 352 | |
| 353 | // ------------------ |
| 354 | // Test PacketIn handling: with a thrown exception. |
| 355 | reset(test1, test2, test3); |
| 356 | expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 357 | .andReturn(Command.CONTINUE); |
| 358 | expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 359 | .andThrow(new RuntimeException("This is NOT an error! We " + |
| 360 | "are testing exception catching.")); |
| 361 | // expect no calls to test3.receive() since test2.receive throws |
| 362 | // an exception |
| 363 | replay(test1, test2, test3); |
| 364 | try { |
| 365 | controller.handleMessage(sw, pi, null); |
| 366 | fail("Expected exception was not thrown!"); |
| 367 | } catch (RuntimeException e) { |
| 368 | assertTrue("The caught exception was not the expected one", |
| 369 | e.getMessage().startsWith("This is NOT an error!")); |
| 370 | } |
| 371 | verify(test1); |
| 372 | verify(test2); |
| 373 | verify(test3); |
| 374 | |
| 375 | // ------------------ |
| 376 | // Test PacketIn handling: test1 return Command.STOP |
| 377 | reset(test1, test2, test3); |
| 378 | expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))) |
| 379 | .andReturn(Command.STOP); |
| 380 | // expect no calls to test3.receive() and test2.receive since |
| 381 | // test1.receive returns STOP |
| 382 | replay(test1, test2, test3); |
| 383 | controller.handleMessage(sw, pi, null); |
| 384 | verify(test1); |
| 385 | verify(test2); |
| 386 | verify(test3); |
| 387 | |
| 388 | OFFlowMod fm = factory10.buildFlowAdd().build(); |
| 389 | |
| 390 | // ------------------ |
| 391 | // Test FlowMod handling: all listeners return CONTINUE |
| 392 | reset(test1, test2, test3); |
| 393 | expect(test1.receive(eq(sw), eq(fm), isA(FloodlightContext.class))) |
| 394 | .andReturn(Command.CONTINUE); |
| 395 | expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class))) |
| 396 | .andReturn(Command.CONTINUE); |
| 397 | // test3 is not a listener for FlowMod |
| 398 | replay(test1, test2, test3); |
| 399 | controller.handleMessage(sw, fm, null); |
| 400 | verify(test1); |
| 401 | verify(test2); |
| 402 | verify(test3); |
| 403 | |
| 404 | // ------------------ |
| 405 | // Test FlowMod handling: test2 (first listener) return STOP |
| 406 | reset(test1, test2, test3); |
| 407 | expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class))) |
| 408 | .andReturn(Command.STOP); |
| 409 | // test2 will not be called |
| 410 | // test3 is not a listener for FlowMod |
| 411 | replay(test1, test2, test3); |
| 412 | controller.handleMessage(sw, fm, null); |
| 413 | verify(test1); |
| 414 | verify(test2); |
| 415 | verify(test3); |
| 416 | |
| 417 | verify(sw); |
| 418 | } |
| 419 | |
| 420 | @Test |
| 421 | public void testHandleMessageWithContext() throws Exception { |
| 422 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 423 | expect(sw.getId()).andReturn(0L).anyTimes(); |
| 424 | expect(sw.getStringId()).andReturn("00:00:00:00:00:00:00").anyTimes(); |
| 425 | expect(sw.getOFVersion()).andReturn(OFVersion.OF_10).anyTimes(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 426 | |
| 427 | IOFMessageListener test1 = createMock(IOFMessageListener.class); |
| 428 | expect(test1.getName()).andReturn("test1").anyTimes(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 429 | expect(test1.isCallbackOrderingPrereq((OFType) anyObject(), |
| 430 | (String) anyObject())) |
| 431 | .andReturn(false).anyTimes(); |
| 432 | expect(test1.isCallbackOrderingPostreq((OFType) anyObject(), |
| 433 | (String) anyObject())) |
| 434 | .andReturn(false).anyTimes(); |
| 435 | FloodlightContext cntx = new FloodlightContext(); |
| 436 | expect(test1.receive(same(sw), same(pi), same(cntx))) |
| 437 | .andReturn(Command.CONTINUE); |
| 438 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 439 | IOFMessageListener test2 = createMock(IOFMessageListener.class); |
| 440 | expect(test2.getName()).andReturn("test2").anyTimes(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 441 | expect(test2.isCallbackOrderingPrereq((OFType) anyObject(), |
| 442 | (String) anyObject())) |
| 443 | .andReturn(false).anyTimes(); |
| 444 | expect(test2.isCallbackOrderingPostreq((OFType) anyObject(), |
| 445 | (String) anyObject())) |
| 446 | .andReturn(false).anyTimes(); |
| 447 | // test2 will not receive any message! |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 448 | |
| 449 | replay(test1, test2, sw); |
| 450 | controller.addOFMessageListener(OFType.PACKET_IN, test1); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 451 | controller.addOFMessageListener(OFType.ERROR, test2); |
| 452 | controller.handleMessage(sw, pi, cntx); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 453 | verify(test1, test2, sw); |
| 454 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 455 | Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, |
| 456 | IFloodlightProviderService.CONTEXT_PI_PAYLOAD); |
| 457 | assertArrayEquals(testPacket.serialize(), eth.serialize()); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | public class FutureFetcher<E> implements Runnable { |
| 461 | public E value; |
| 462 | public Future<E> future; |
| 463 | |
| 464 | public FutureFetcher(Future<E> future) { |
| 465 | this.future = future; |
| 466 | } |
| 467 | |
| 468 | @Override |
| 469 | public void run() { |
| 470 | try { |
| 471 | value = future.get(); |
| 472 | } catch (Exception e) { |
| 473 | throw new RuntimeException(e); |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | /** |
| 478 | * @return the value |
| 479 | */ |
| 480 | public E getValue() { |
| 481 | return value; |
| 482 | } |
| 483 | |
| 484 | /** |
| 485 | * @return the future |
| 486 | */ |
| 487 | public Future<E> getFuture() { |
| 488 | return future; |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | /** |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 493 | * @throws Exception |
| 494 | */ |
| 495 | @Test |
| 496 | public void testOFStatisticsFuture() throws Exception { |
| 497 | // Test for a single stats reply |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 498 | OFSwitchImplBase sw = createMock(OFSwitchImplBase.class); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 499 | sw.cancelStatisticsReply(1); |
| 500 | OFStatisticsFuture sf = new OFStatisticsFuture(tp, sw, 1); |
| 501 | |
| 502 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 503 | List<OFStatsReply> stats; |
| 504 | FutureFetcher<List<OFStatsReply>> ff = new FutureFetcher<List<OFStatsReply>>(sf); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 505 | Thread t = new Thread(ff); |
| 506 | t.start(); |
| 507 | sf.deliverFuture(sw, getStatisticsReply(1, 10, false)); |
| 508 | |
| 509 | t.join(); |
| 510 | stats = ff.getValue(); |
| 511 | verify(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 512 | // TODO: temporary fix: size = 1 ? |
| 513 | assertEquals(1, stats.size()); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 514 | |
| 515 | // Test multiple stats replies |
| 516 | reset(sw); |
| 517 | sw.cancelStatisticsReply(1); |
| 518 | |
| 519 | sf = new OFStatisticsFuture(tp, sw, 1); |
| 520 | |
| 521 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 522 | ff = new FutureFetcher<List<OFStatsReply>>(sf); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 523 | t = new Thread(ff); |
| 524 | t.start(); |
| 525 | sf.deliverFuture(sw, getStatisticsReply(1, 10, true)); |
| 526 | sf.deliverFuture(sw, getStatisticsReply(1, 5, false)); |
| 527 | t.join(); |
| 528 | |
| 529 | stats = sf.get(); |
| 530 | verify(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 531 | // TODO: temporary fix: size = 2 ? |
| 532 | assertEquals(2, stats.size()); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 533 | |
| 534 | // Test cancellation |
| 535 | reset(sw); |
| 536 | sw.cancelStatisticsReply(1); |
| 537 | sf = new OFStatisticsFuture(tp, sw, 1); |
| 538 | |
| 539 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 540 | ff = new FutureFetcher<List<OFStatsReply>>(sf); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 541 | t = new Thread(ff); |
| 542 | t.start(); |
| 543 | sf.cancel(true); |
| 544 | t.join(); |
| 545 | |
| 546 | stats = sf.get(); |
| 547 | verify(sw); |
| 548 | assertEquals(0, stats.size()); |
| 549 | |
| 550 | // Test self timeout |
| 551 | reset(sw); |
| 552 | sw.cancelStatisticsReply(1); |
| 553 | sf = new OFStatisticsFuture(tp, sw, 1, 75, TimeUnit.MILLISECONDS); |
| 554 | |
| 555 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 556 | ff = new FutureFetcher<List<OFStatsReply>>(sf); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 557 | t = new Thread(ff); |
| 558 | t.start(); |
| 559 | t.join(2000); |
| 560 | |
| 561 | stats = sf.get(); |
| 562 | verify(sw); |
| 563 | assertEquals(0, stats.size()); |
| 564 | } |
| 565 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 566 | /** |
| 567 | * Test switchActivated for a new switch, i.e., a switch that was not |
| 568 | * previously known to the controller cluser. We expect that all flow mods |
| 569 | * are cleared and we expect a switchAdded |
| 570 | */ |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 571 | @Test |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 572 | public void testNewSwitchActivated() throws Exception { |
| 573 | controller.setAlwaysClearFlowsOnSwActivate(false); |
| 574 | controller.setAlwaysClearFlowsOnSwAdd(false); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 575 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 576 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 577 | expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes(); |
| 578 | setupSwitchForAddSwitch(sw, 0L, null, null); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 579 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 580 | // strict mock. Order of events matters! |
| 581 | IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class); |
| 582 | listener.switchActivatedMaster(0L); |
| 583 | expectLastCall().once(); |
| 584 | replay(listener); |
| 585 | controller.addOFSwitchListener(listener); |
| 586 | |
| 587 | replay(sw); |
| 588 | controller.addConnectedSwitch(0L, new OFChannelHandler(controller)); |
| 589 | controller.addActivatedMasterSwitch(0L, sw); |
| 590 | verify(sw); |
| 591 | assertEquals(sw, controller.getMasterSwitch(0L)); |
| 592 | controller.processUpdateQueueForTesting(); |
| 593 | verify(listener); |
| 594 | } |
| 595 | |
| 596 | /** |
| 597 | * Test switchActivated for a new switch while in equal: a no-op |
| 598 | */ |
| 599 | @Test |
| 600 | public void testNewSwitchActivatedWhileSlave() throws Exception { |
| 601 | doSetUp(Role.EQUAL); |
| 602 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 603 | |
| 604 | IOFSwitchListener listener = createMock(IOFSwitchListener.class); |
| 605 | controller.addOFSwitchListener(listener); |
| 606 | |
| 607 | replay(sw, listener); // nothing recorded |
| 608 | controller.addConnectedSwitch(0L, new OFChannelHandler(controller)); |
| 609 | controller.addActivatedEqualSwitch(0L, sw); |
| 610 | verify(sw); |
| 611 | verify(listener); |
| 612 | } |
| 613 | |
| 614 | /** |
| 615 | * Disconnect a switch. normal program flow |
| 616 | */ |
| 617 | @Test |
| 618 | private void doTestSwitchConnectReconnect(boolean reconnect) |
| 619 | throws Exception { |
| 620 | IOFSwitch sw = doActivateNewSwitch(1L, null, null); |
| 621 | expect(sw.getId()).andReturn(1L).anyTimes(); |
| 622 | expect(sw.getStringId()).andReturn(HexString.toHexString(1L)).anyTimes(); |
| 623 | sw.setConnected(false); |
| 624 | expectLastCall().once(); |
| 625 | sw.cancelAllStatisticsReplies(); |
| 626 | expectLastCall().once(); |
| 627 | IOFSwitchListener listener = createMock(IOFSwitchListener.class); |
| 628 | listener.switchDisconnected(1L); |
| 629 | expectLastCall().once(); |
| 630 | controller.addOFSwitchListener(listener); |
| 631 | replay(sw, listener); |
| 632 | controller.removeConnectedSwitch(1L); |
| 633 | controller.processUpdateQueueForTesting(); |
| 634 | verify(sw, listener); |
| 635 | |
| 636 | assertNull(controller.getSwitch(1L)); |
| 637 | if (reconnect) { |
| 638 | controller.removeOFSwitchListener(listener); |
| 639 | sw = doActivateOldSwitch(1L, null, null); |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | @Test |
| 644 | public void testSwitchDisconnected() throws Exception { |
| 645 | doTestSwitchConnectReconnect(false); |
| 646 | } |
| 647 | |
| 648 | /** |
| 649 | * Disconnect a switch and reconnect, verify no clearAllFlowmods() |
| 650 | */ |
| 651 | @Test |
| 652 | public void testSwitchReconnect() throws Exception { |
| 653 | doTestSwitchConnectReconnect(true); |
| 654 | } |
| 655 | |
| 656 | /* /** |
| 657 | * Remove a nonexisting switch. should be ignored |
| 658 | */ |
| 659 | @Test |
| 660 | public void testNonexistingSwitchDisconnected() throws Exception { |
| 661 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 662 | expect(sw.getId()).andReturn(1L).anyTimes(); |
| 663 | expect(sw.getStringId()).andReturn(HexString.toHexString(1L)).anyTimes(); |
| 664 | IOFSwitchListener listener = createMock(IOFSwitchListener.class); |
| 665 | controller.addOFSwitchListener(listener); |
| 666 | replay(sw, listener); |
| 667 | controller.removeConnectedSwitch(sw.getId()); |
| 668 | // controller.processUpdateQueueForTesting(); |
| 669 | verify(sw, listener); |
| 670 | |
| 671 | assertNull(controller.getSwitch(1L)); |
| 672 | } |
| 673 | |
| 674 | /** |
| 675 | * Try to activate a switch that's already active (which can happen if two |
| 676 | * different switches have the same DPIP or if a switch reconnects while the |
| 677 | * old TCP connection is still alive |
| 678 | */ |
| 679 | // TODO: I do not if it represents the expected behaviour |
| 680 | @Test |
| 681 | public void testSwitchActivatedWithAlreadyActiveSwitch() throws Exception { |
| 682 | OFDescStatsReply oldDesc = createOFDescStatsReply(); |
| 683 | oldDesc.createBuilder().setDpDesc("Ye Olde Switch"); |
| 684 | OFDescStatsReply newDesc = createOFDescStatsReply(); |
| 685 | oldDesc.createBuilder().setDpDesc("The new Switch"); |
| 686 | OFFeaturesReply featuresReply = createOFFeaturesReply(); |
| 687 | |
| 688 | // Setup: add a switch to the controller |
| 689 | IOFSwitch oldsw = createMock(IOFSwitch.class); |
| 690 | setupSwitchForAddSwitch(oldsw, 0L, oldDesc, featuresReply); |
| 691 | expect(oldsw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes(); |
| 692 | // oldsw.clearAllFlowMods(); |
| 693 | // expectLastCall().once(); |
| 694 | replay(oldsw); |
| 695 | controller.addConnectedSwitch(oldsw.getId(), new OFChannelHandler(controller)); |
| 696 | controller.addActivatedMasterSwitch(oldsw.getId(), oldsw); |
| 697 | verify(oldsw); |
| 698 | // drain the queue, we don't care what's in it |
| 699 | controller.processUpdateQueueForTesting(); |
| 700 | assertEquals(oldsw, controller.getSwitch(0L)); |
| 701 | |
| 702 | // Now the actual test: add a new switch with the same dpid to |
| 703 | // the controller |
| 704 | reset(oldsw); |
| 705 | expect(oldsw.getId()).andReturn(0L).anyTimes(); |
| 706 | // oldsw.cancelAllStatisticsReplies(); |
| 707 | // expectLastCall().once(); |
| 708 | // oldsw.disconnectOutputStream(); |
| 709 | // expectLastCall().once(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 710 | |
| 711 | IOFSwitch newsw = createMock(IOFSwitch.class); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 712 | setupSwitchForAddSwitch(newsw, 0L, newDesc, featuresReply); |
| 713 | // newsw.clearAllFlowMods(); |
| 714 | // expectLastCall().once(); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 715 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 716 | // Strict mock. We need to get the removed notification before the |
| 717 | // add notification |
| 718 | IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class); |
| 719 | // listener.switchDisconnected(0L); |
| 720 | // listener.switchActivatedMaster(0L); |
| 721 | replay(listener); |
| 722 | controller.addOFSwitchListener(listener); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 723 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 724 | replay(newsw, oldsw); |
| 725 | controller.addActivatedMasterSwitch(0L, newsw); |
| 726 | verify(newsw, oldsw); |
| 727 | |
| 728 | assertEquals(oldsw, controller.getSwitch(0L)); |
| 729 | controller.processUpdateQueueForTesting(); |
| 730 | verify(listener); |
| 731 | } |
| 732 | |
| 733 | /** |
| 734 | * Tests that you can't remove a switch from the map returned by |
| 735 | * getSwitches() (because getSwitches should return an unmodifiable map) |
| 736 | */ |
| 737 | @Test |
| 738 | public void testRemoveActiveSwitch() { |
| 739 | IOFSwitch sw = createNiceMock(IOFSwitch.class); |
| 740 | expect(sw.getPorts()).andReturn(new ArrayList<OFPortDesc>()).anyTimes(); |
| 741 | setupSwitchForAddSwitch(sw, 1L, null, null); |
| 742 | replay(sw); |
| 743 | controller.addConnectedSwitch(1L, new OFChannelHandler(controller)); |
| 744 | controller.addActivatedMasterSwitch(1L, sw); |
| 745 | assertEquals(sw, getController().getSwitch(1L)); |
| 746 | controller.getAllSwitchDpids().remove(1L); |
| 747 | assertEquals(sw, getController().getSwitch(1L)); |
| 748 | verify(sw); |
| 749 | // we don't care for updates. drain queue. |
| 750 | controller.processUpdateQueueForTesting(); |
| 751 | } |
| 752 | |
| 753 | /** |
| 754 | * Create and activate a switch, either completely new or reconnected The |
| 755 | * mocked switch instance will be returned. It wil be reset. |
| 756 | */ |
| 757 | private IOFSwitch doActivateSwitchInt(long dpid, |
| 758 | OFDescStatsReply desc, |
| 759 | OFFeaturesReply featuresReply, |
| 760 | boolean clearFlows) |
| 761 | throws Exception { |
| 762 | controller.setAlwaysClearFlowsOnSwActivate(false); |
| 763 | |
| 764 | IOFSwitch sw = createMock(IOFSwitch.class); |
| 765 | if (featuresReply == null) { |
| 766 | featuresReply = createOFFeaturesReply(); |
| 767 | featuresReply.createBuilder().setDatapathId(DatapathId.of(dpid)); |
| 768 | } |
| 769 | if (desc == null) { |
| 770 | desc = createOFDescStatsReply(); |
| 771 | } |
| 772 | setupSwitchForAddSwitch(sw, dpid, desc, featuresReply); |
| 773 | if (clearFlows) { |
| 774 | sw.clearAllFlowMods(); |
| 775 | expectLastCall().once(); |
| 776 | } |
| 777 | expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes(); |
| 778 | |
| 779 | replay(sw); |
| 780 | controller.addConnectedSwitch(dpid, new OFChannelHandler(controller)); |
| 781 | controller.addActivatedMasterSwitch(dpid, sw); |
| 782 | verify(sw); |
| 783 | assertEquals(sw, controller.getSwitch(dpid)); |
| 784 | // drain updates and ignore |
| 785 | controller.processUpdateQueueForTesting(); |
| 786 | |
| 787 | // SwitchSyncRepresentation storedSwitch = storeClient.getValue(dpid); |
| 788 | // assertEquals(featuresReply, storedSwitch.getFeaturesReply()); |
| 789 | // assertEquals(desc, storedSwitch.getDescription()); |
| 790 | reset(sw); |
| 791 | return sw; |
| 792 | } |
| 793 | |
| 794 | /** |
| 795 | * Create and activate a new switch with the given dpid, features reply and |
| 796 | * description. If description and/or features reply are null we'll allocate |
| 797 | * the default one The mocked switch instance will be returned. It wil be |
| 798 | * reset. |
| 799 | */ |
| 800 | private IOFSwitch doActivateNewSwitch(long dpid, |
| 801 | OFDescStatsReply desc, |
| 802 | OFFeaturesReply featuresReply) |
| 803 | throws Exception { |
| 804 | return doActivateSwitchInt(dpid, desc, featuresReply, false); |
| 805 | } |
| 806 | |
| 807 | /** |
| 808 | * Create and activate a switch that's just been disconnected. The mocked |
| 809 | * switch instance will be returned. It wil be reset. |
| 810 | */ |
| 811 | private IOFSwitch doActivateOldSwitch(long dpid, |
| 812 | OFDescStatsReply desc, |
| 813 | OFFeaturesReply featuresReply) |
| 814 | throws Exception { |
| 815 | return doActivateSwitchInt(dpid, desc, featuresReply, false); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 816 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 817 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 818 | @Test |
| 819 | public void testUpdateQueue() throws Exception { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 820 | class DummySwitchListener implements IOFSwitchListener { |
| 821 | public int nAddedMaster; |
| 822 | public int nAddedEqual; |
| 823 | public int nDisconnected; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 824 | public int nPortChanged; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 825 | public int nPortAdded; |
| 826 | public int nPortDeleted; |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 827 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 828 | public DummySwitchListener() { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 829 | nAddedMaster = 0; |
| 830 | nAddedEqual = 0; |
| 831 | nDisconnected = 0; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 832 | nPortChanged = 0; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 833 | nPortAdded = 0; |
| 834 | nPortDeleted = 0; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 835 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 836 | |
Yuta HIGUCHI | 0b7c19e | 2014-07-21 23:33:20 -0700 | [diff] [blame] | 837 | @Override |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 838 | public String getName() { |
| 839 | return "dummy"; |
| 840 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 841 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 842 | @Override |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 843 | public void switchActivatedMaster(long swId) { |
| 844 | nAddedMaster++; |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 845 | notifyAll(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 846 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 847 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 848 | |
| 849 | @Override |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 850 | public void switchActivatedEqual(long swId) { |
| 851 | nAddedEqual++; |
| 852 | notifyAll(); |
| 853 | |
| 854 | } |
| 855 | |
| 856 | @Override |
| 857 | public void switchMasterToEqual(long swId) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 858 | // TODO Auto-generated method stub |
| 859 | |
| 860 | } |
| 861 | |
| 862 | @Override |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 863 | public void switchEqualToMaster(long swId) { |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 864 | // TODO Auto-generated method stub |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 865 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 866 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 867 | @Override |
| 868 | public void switchDisconnected(long swId) { |
| 869 | nDisconnected++; |
| 870 | notifyAll(); |
| 871 | |
| 872 | } |
| 873 | |
| 874 | @Override |
| 875 | public void switchPortChanged(long swId, OFPortDesc port, |
| 876 | PortChangeType changeType) { |
| 877 | switch (changeType) { |
| 878 | case ADD: |
| 879 | nPortAdded++; |
| 880 | notifyAll(); |
| 881 | break; |
| 882 | case DELETE: |
| 883 | nPortDeleted++; |
| 884 | notifyAll(); |
| 885 | break; |
| 886 | |
| 887 | case OTHER_UPDATE: |
| 888 | nPortChanged++; |
| 889 | notifyAll(); |
| 890 | break; |
| 891 | |
| 892 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 893 | } |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 894 | } |
| 895 | DummySwitchListener switchListener = new DummySwitchListener(); |
| 896 | IOFSwitch sw = createMock(IOFSwitch.class); |
Jonathan Hart | 220b829 | 2013-12-07 19:25:11 -0800 | [diff] [blame] | 897 | expect(sw.getId()).andReturn(1L).anyTimes(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 898 | expect(sw.getPort(1)).andReturn(factory10.buildPortDesc().build()).anyTimes(); |
Jonathan Hart | 220b829 | 2013-12-07 19:25:11 -0800 | [diff] [blame] | 899 | replay(sw); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 900 | ControllerRunThread t = new ControllerRunThread(); |
| 901 | t.start(); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 902 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 903 | controller.addOFSwitchListener(switchListener); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 904 | synchronized (switchListener) { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 905 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 906 | Controller.SwitchUpdateType.ACTIVATED_MASTER)); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 907 | switchListener.wait(500); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 908 | assertTrue("IOFSwitchListener.addedSwitch() was not called", |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 909 | switchListener.nAddedMaster == 1); |
| 910 | controller.addOFSwitchListener(switchListener); |
| 911 | synchronized (switchListener) { |
| 912 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 913 | Controller.SwitchUpdateType.ACTIVATED_EQUAL)); |
| 914 | switchListener.wait(500); |
| 915 | assertTrue("IOFSwitchListener.addedSwitch() was not called", |
| 916 | switchListener.nAddedEqual == 1); |
| 917 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 918 | Controller.SwitchUpdateType.DISCONNECTED)); |
| 919 | switchListener.wait(500); |
| 920 | assertTrue("IOFSwitchListener.removedSwitch() was not called", |
| 921 | switchListener.nDisconnected == 1); |
| 922 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 923 | Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1), |
| 924 | PortChangeType.ADD)); |
| 925 | switchListener.wait(500); |
| 926 | assertTrue( |
| 927 | "IOFSwitchListener.switchPortChanged() with PortChangeType.ADD was not called", |
| 928 | switchListener.nPortAdded == 1); |
| 929 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 930 | Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1), |
| 931 | PortChangeType.DELETE)); |
| 932 | switchListener.wait(500); |
| 933 | assertTrue( |
| 934 | "IOFSwitchListener.switchPortChanged() with PortChangeType.DELETE was not called", |
| 935 | switchListener.nPortDeleted == 1); |
| 936 | controller.updates.put(controller.new SwitchUpdate(sw.getId(), |
| 937 | Controller.SwitchUpdateType.PORTCHANGED, sw.getPort(1), |
| 938 | PortChangeType.OTHER_UPDATE)); |
| 939 | switchListener.wait(500); |
| 940 | assertTrue( |
| 941 | "IOFSwitchListener.switchPortChanged() with PortChangeType.OTHER_UPDATE was not called", |
| 942 | switchListener.nPortChanged == 1); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 943 | } |
| 944 | } |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 945 | } |
| 946 | |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 947 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 948 | public void verifyPortChangedUpdateInQueue(IOFSwitch sw) throws Exception { |
| 949 | assertEquals(1, controller.updates.size()); |
| 950 | IUpdate update = controller.updates.take(); |
| 951 | assertEquals(true, update instanceof SwitchUpdate); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 952 | SwitchUpdate swUpdate = (SwitchUpdate) update; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 953 | assertEquals(sw.getId(), swUpdate.getSwId()); |
| 954 | assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType()); |
| 955 | assertEquals(PortChangeType.OTHER_UPDATE, swUpdate.getPortChangeType()); |
| 956 | } |
| 957 | |
| 958 | public void verifyPortDownUpdateInQueue(IOFSwitch sw) throws Exception { |
| 959 | assertEquals(1, controller.updates.size()); |
| 960 | IUpdate update = controller.updates.take(); |
| 961 | assertEquals(true, update instanceof SwitchUpdate); |
| 962 | SwitchUpdate swUpdate = (SwitchUpdate) update; |
| 963 | assertEquals(sw.getId(), swUpdate.getSwId()); |
| 964 | assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType()); |
| 965 | assertEquals(PortChangeType.DOWN, swUpdate.getPortChangeType()); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 966 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 967 | |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 968 | public void verifyPortAddedUpdateInQueue(IOFSwitch sw) throws Exception { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 969 | assertEquals(1, controller.updates.size()); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 970 | IUpdate update = controller.updates.take(); |
| 971 | assertEquals(true, update instanceof SwitchUpdate); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 972 | SwitchUpdate swUpdate = (SwitchUpdate) update; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 973 | assertEquals(sw.getId(), swUpdate.getSwId()); |
| 974 | assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType()); |
| 975 | assertEquals(PortChangeType.ADD, swUpdate.getPortChangeType()); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 976 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 977 | |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 978 | public void verifyPortRemovedUpdateInQueue(IOFSwitch sw) throws Exception { |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 979 | assertEquals(1, controller.updates.size()); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 980 | IUpdate update = controller.updates.take(); |
| 981 | assertEquals(true, update instanceof SwitchUpdate); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 982 | SwitchUpdate swUpdate = (SwitchUpdate) update; |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 983 | assertEquals(sw.getId(), swUpdate.getSwId()); |
| 984 | assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.getSwitchUpdateType()); |
| 985 | assertEquals(PortChangeType.DELETE, swUpdate.getPortChangeType()); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 986 | } |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 987 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 988 | // * Test handlePortStatus() |
| 989 | // * |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 990 | @Test |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 991 | public void testHandlePortStatus() throws Exception { |
| 992 | IOFSwitch sw = createMock(IOFSwitch.class); |
Jonathan Hart | 220b829 | 2013-12-07 19:25:11 -0800 | [diff] [blame] | 993 | expect(sw.getId()).andReturn(1L).anyTimes(); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 994 | //expect(sw.getPorts()).andReturn(new HashSet<OFPortDesc>()).anyTimes(); |
| 995 | OFPortDesc port = factory10.buildPortDesc() |
| 996 | .setName("myPortName1") |
| 997 | .setPortNo(OFPort.of(42)) |
| 998 | .build(); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 999 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1000 | controller.connectedSwitches.put(1L, new OFChannelHandler(controller)); |
| 1001 | controller.activeMasterSwitches.put(1L, sw); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 1002 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1003 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1004 | controller.notifyPortChanged(sw.getId(), port, PortChangeType.ADD); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1005 | verify(sw); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 1006 | verifyPortAddedUpdateInQueue(sw); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1007 | reset(sw); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 1008 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1009 | expect(sw.getId()).andReturn(1L).anyTimes(); |
| 1010 | |
| 1011 | Set<OFPortState> ofPortStates = new HashSet<OFPortState>(); |
| 1012 | ofPortStates.add(OFPortState.LINK_DOWN); |
| 1013 | port.createBuilder().setState(ofPortStates); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1014 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1015 | controller.notifyPortChanged(sw.getId(), port, PortChangeType.OTHER_UPDATE); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1016 | verify(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1017 | verifyPortChangedUpdateInQueue(sw); |
| 1018 | reset(sw); |
| 1019 | ofPortStates = new HashSet<OFPortState>(); |
| 1020 | port.createBuilder().setState(ofPortStates); |
| 1021 | |
| 1022 | expect(sw.getId()).andReturn(1L).anyTimes(); |
| 1023 | |
| 1024 | port.createBuilder().setState(ofPortStates); |
| 1025 | replay(sw); |
| 1026 | controller.notifyPortChanged(sw.getId(), port, PortChangeType.DOWN); |
| 1027 | verify(sw); |
| 1028 | verifyPortDownUpdateInQueue(sw); |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1029 | reset(sw); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 1030 | |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1031 | expect(sw.getId()).andReturn(1L).anyTimes(); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 1032 | replay(sw); |
Brian O'Connor | c67f9fa | 2014-08-07 18:17:46 -0700 | [diff] [blame^] | 1033 | controller.notifyPortChanged(sw.getId(), port, PortChangeType.DELETE); |
HIGUCHI Yuta | 21fd07f | 2013-06-28 11:24:14 -0700 | [diff] [blame] | 1034 | verify(sw); |
| 1035 | verifyPortRemovedUpdateInQueue(sw); |
| 1036 | reset(sw); |
Ray Milkey | 269ffb9 | 2014-04-03 14:43:30 -0700 | [diff] [blame] | 1037 | |
Umesh Krishnaswamy | 345ee99 | 2012-12-13 20:29:48 -0800 | [diff] [blame] | 1038 | } |
| 1039 | } |