/* * Copyright 2016-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.rabbitmq.listener; import static com.google.common.collect.ImmutableSet.of; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.onosproject.net.DeviceId.deviceId; import static org.onosproject.net.NetTestTools.device; import static org.onosproject.net.NetTestTools.link; import static org.onosproject.net.PortNumber.portNumber; import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; import static org.onosproject.net.device.DeviceEvent.Type.*; import static org.onosproject.net.link.LinkEvent.Type.*; import static org.onosproject.net.Device.Type.*; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.easymock.EasyMockRunner; import org.easymock.Mock; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.onlab.packet.ChassisId; import org.onlab.packet.Ethernet; import org.onlab.packet.ONOSLLDP; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.core.DefaultApplicationId; import org.onosproject.event.AbstractEventTest; import org.onosproject.event.Event; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DefaultDevice; import org.onosproject.net.DefaultLink; import org.onosproject.net.DefaultPort; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Link; import org.onosproject.net.link.LinkEvent; import org.onosproject.net.MastershipRole; import org.onosproject.net.Port; import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceServiceAdapter; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.link.LinkListener; import org.onosproject.net.link.LinkService; import org.onosproject.net.packet.DefaultInboundPacket; import org.onosproject.net.packet.InboundPacket; import org.onosproject.net.packet.OutboundPacket; import org.onosproject.net.packet.PacketContext; import org.onosproject.net.packet.PacketProcessor; import org.onosproject.net.packet.PacketServiceAdapter; import org.onosproject.net.provider.AbstractProvider; import org.onosproject.net.provider.ProviderId; import org.onosproject.net.topology.DefaultGraphDescription; import org.onosproject.net.topology.GraphDescription; import org.onosproject.net.topology.Topology; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; import org.onosproject.net.topology.TopologyProvider; import org.onosproject.net.topology.TopologyProviderRegistry; import org.onosproject.net.topology.TopologyProviderService; import org.onosproject.net.topology.TopologyService; import org.onosproject.rabbitmq.api.MQService; import org.onosproject.rabbitmq.api.Manageable; import org.osgi.service.component.ComponentContext; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.util.concurrent.MoreExecutors; /** * Junit tests for packet in, device, topology and link events. */ @RunWith(EasyMockRunner.class) public class MQEventHandlerTest extends AbstractEventTest { private final MQEventHandler mqEventHandler = new MQEventHandler(); private static final DeviceId DID1 = deviceId("of:0000000000000001"); private static final DeviceId DID2 = deviceId("of:0000000000000002"); private static final DeviceId DID3 = deviceId("of:0000000000000003"); private ApplicationId appId = new DefaultApplicationId(100, "org.onosproject.rabbitmq"); private final TestPacketService packetService = new TestPacketService(); private final TestDeviceService deviceService = new TestDeviceService(); private PacketProcessor testProcessor; private DeviceListener deviceListener; private static Port pd1; private static Port pd2; private static Port pd3; private static Port pd4; private CoreService coreService; @Mock ComponentContext context; @Mock private Manageable manageSender; private static final ProviderId PID = new ProviderId("of", "foo"); private TestLinkListener testLinkListener = new TestLinkListener(); @Mock private LinkService linkService; @Mock Topology topology; @Mock protected TopologyService service; protected TopologyProviderRegistry registry; @Mock protected TopologyProviderService providerService; protected TestProvider provider; protected TestTopologyListener listener = new TestTopologyListener(); @Mock MQService mqService; @Before public void setUp() { coreService = createMock(CoreService.class); expect(coreService.registerApplication(appId.name())) .andReturn(appId).anyTimes(); replay(coreService); mqEventHandler.deviceService = deviceService; mqEventHandler.packetService = packetService; mqEventHandler.eventExecutor = MoreExecutors.newDirectExecutorService(); linkService.addListener(testLinkListener); mqEventHandler.linkService = linkService; mqEventHandler.topologyService = service; mqEventHandler.activate(context); } @After public void tearDown() { mqEventHandler.deactivate(); mqEventHandler.deviceService = null; mqEventHandler.packetService = null; } private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) { return new DeviceEvent(type, deviceService.getDevice(did)); } private Port port(DeviceId did, long port, boolean enabled) { return new DefaultPort(deviceService.getDevice(did), portNumber(port), enabled); } private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) { return new DeviceEvent(type, deviceService.getDevice(did), port); } @Test public void switchAdd() { DeviceEvent de = deviceEvent(DEVICE_ADDED, DID1); deviceListener.event(de); } @Test public void switchRemove() { deviceListener.event(deviceEvent(DEVICE_ADDED, DID1)); deviceListener.event(deviceEvent(DEVICE_REMOVED, DID1)); } @Test public void switchUpdate() { deviceListener.event(deviceEvent(DEVICE_UPDATED, DID1)); deviceListener.event(deviceEvent(DEVICE_REMOVED, DID1)); } @Test public void switchSuspend() { deviceListener.event(deviceEvent(DEVICE_SUSPENDED, DID1)); deviceListener.event(deviceEvent(DEVICE_REMOVED, DID1)); } @Test public void portUp() { deviceListener.event(deviceEvent(DEVICE_ADDED, DID1)); deviceListener.event(portEvent(PORT_ADDED, DID1, port(DID1, 3, true))); } @Test public void portDown() { deviceListener.event(deviceEvent(DEVICE_ADDED, DID1)); deviceListener.event(portEvent(PORT_ADDED, DID1, port(DID1, 1, false))); } @Test public void portRemoved() { deviceListener.event(deviceEvent(DEVICE_ADDED, DID1)); deviceListener.event(portEvent(PORT_ADDED, DID1, port(DID1, 3, true))); deviceListener.event(portEvent(PORT_REMOVED, DID1, port(DID1, 3, true))); } @Test public void unknownPktCtx() { // Note: DID3 hasn't been added to TestDeviceService PacketContext pktCtx = new TestPacketContext(device1(DID3)); testProcessor.process(pktCtx); assertFalse("Context should still be free", pktCtx.isHandled()); } private DefaultDevice device1(DeviceId did) { return new DefaultDevice(ProviderId.NONE, did, SWITCH, "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); } @Test public void knownPktCtx() { deviceListener.event(deviceEvent(DEVICE_ADDED, DID1)); deviceListener.event(deviceEvent(DEVICE_ADDED, DID2)); PacketContext pktCtx = new TestPacketContext( deviceService.getDevice(DID2)); /* * EasyMock.expectLastCall(); EasyMock.replay(manageSender); */ testProcessor.process(pktCtx); } private class TestDeviceService extends DeviceServiceAdapter { private final Map<DeviceId, Device> devices = new HashMap<>(); private final ArrayListMultimap<DeviceId, Port> ports = ArrayListMultimap.create(); public TestDeviceService() { Device d1 = new DefaultDevice(ProviderId.NONE, DID1, SWITCH, "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); Device d2 = new DefaultDevice(ProviderId.NONE, DID2, SWITCH, "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); devices.put(DID1, d1); devices.put(DID2, d2); pd1 = new DefaultPort(d1, portNumber(1), true); pd2 = new DefaultPort(d1, portNumber(2), true); pd3 = new DefaultPort(d2, portNumber(1), true); pd4 = new DefaultPort(d2, portNumber(2), true); ports.putAll(DID1, Lists.newArrayList(pd1, pd2)); ports.putAll(DID2, Lists.newArrayList(pd3, pd4)); } @Override public int getDeviceCount() { return devices.values().size(); } @Override public Iterable<Device> getDevices() { return ImmutableList.copyOf(devices.values()); } @Override public Device getDevice(DeviceId deviceId) { return devices.get(deviceId); } @Override public MastershipRole getRole(DeviceId deviceId) { return MastershipRole.MASTER; } @Override public boolean isAvailable(DeviceId deviceId) { return true; } @Override public void addListener(DeviceListener listener) { deviceListener = listener; } @Override public void removeListener(DeviceListener listener) { } } private class TestPacketService extends PacketServiceAdapter { @Override public void addProcessor(PacketProcessor processor, int priority) { testProcessor = processor; } } private class TestPacketContext implements PacketContext { protected Device device; protected boolean blocked = false; public TestPacketContext(Device dev) { device = dev; } @Override public long time() { return 0; } @Override public InboundPacket inPacket() { ONOSLLDP lldp = ONOSLLDP.onosLLDP(deviceService.getDevice(DID1) .id().toString(), device.chassisId(), (int) pd1.number().toLong()); Ethernet ethPacket = new Ethernet(); ethPacket.setEtherType(Ethernet.TYPE_LLDP); ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB); ethPacket.setPayload(lldp); ethPacket.setPad(true); ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11"); ConnectPoint cp = new ConnectPoint(device.id(), pd3.number()); return new DefaultInboundPacket(cp, ethPacket, ByteBuffer.wrap(ethPacket .serialize())); } @Override public OutboundPacket outPacket() { return null; } @Override public TrafficTreatment.Builder treatmentBuilder() { return null; } @Override public void send() { } @Override public boolean block() { blocked = true; return blocked; } @Override public boolean isHandled() { return blocked; } } private void submitTopologyGraph() { Set<Device> devices = of(device("a"), device("b"), device("c"), device("d"), device("e"), device("f")); Set<Link> links = of(link("a", 1, "b", 1), link("b", 1, "a", 1), link("b", 2, "c", 1), link("c", 1, "b", 2), link("c", 2, "d", 1), link("d", 1, "c", 2), link("d", 2, "a", 2), link("a", 2, "d", 2), link("e", 1, "f", 1), link("f", 1, "e", 1)); GraphDescription data = new DefaultGraphDescription(4321L, System.currentTimeMillis(), devices, links); providerService.topologyChanged(data, null); } protected void validateEvents(Enum... types) { int i = 0; for (Event event : listener.events) { assertEquals("incorrect event type", types[i], event.type()); i++; } listener.events.clear(); } @Test public void testCreateTopology() { submitTopologyGraph(); validateEvents(TOPOLOGY_CHANGED); } private class TestProvider extends AbstractProvider implements TopologyProvider { public TestProvider() { super(PID); } @Override public void triggerRecompute() { } } private class TestTopologyListener implements TopologyListener { final List<TopologyEvent> events = new ArrayList<>(); @Override public void event(TopologyEvent event) { mqService.publish(event); } } private Link createLink() { return DefaultLink.builder().providerId(new ProviderId("of", "foo")) .src(new ConnectPoint(deviceId("of:foo"), portNumber(1))) .dst(new ConnectPoint(deviceId("of:bar"), portNumber(2))) .type(Link.Type.INDIRECT).build(); } @Test public void testAddLink() throws Exception { Link link = createLink(); LinkEvent event = new LinkEvent(LINK_ADDED, link, 123L); validateEvent(event, LINK_ADDED, link, 123L); } @Test public void testUpdateLink() throws Exception { Link link = createLink(); LinkEvent event = new LinkEvent(LINK_UPDATED, link, 123L); validateEvent(event, LINK_UPDATED, link, 123L); } @Test public void testRemoveLink() throws Exception { Link link = createLink(); LinkEvent event = new LinkEvent(LINK_ADDED, link, 123L); validateEvent(event, LINK_ADDED, link, 123L); LinkEvent event1 = new LinkEvent(LINK_REMOVED, link, 123L); validateEvent(event1, LINK_REMOVED, link, 123L); } private class TestLinkListener implements LinkListener { @Override public void event(LinkEvent event) { mqService.publish(event); } } }