From 09df17bb630b5bf594efbd9f869ef17da5e2b6ac Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Mon, 26 Sep 2016 08:28:20 +0200 Subject: HONEYCOMB-195: increase v3po coverage over 80%. WIP Change-Id: Ibe14d7203bdaf53b925e4d16b598942b62b65bae Signed-off-by: Marek Gradzki --- .../translate/v3po/InterfacesWriterFactory.java | 2 +- .../v3po/interfaces/ProxyArpCustomizer.java | 17 +-- .../v3po/interfaces/InterfaceCustomizerTest.java | 116 ++++++++++++++++ .../v3po/interfaces/L2CustomizerTest.java | 150 +++++++++++++++++++++ .../v3po/interfaces/ProxyArpCustomizerTest.java | 63 +++++++-- .../v3po/interfaces/RoutingCustomizerTest.java | 98 ++++++++++++++ .../interfaces/SubInterfaceAclCustomizerTest.java | 139 +++++++++++++++++++ .../interfaces/SubInterfaceL2CustomizerTest.java | 109 +++++++++++++++ .../interfaces/ip/Ipv4AddressCustomizerTest.java | 35 ++++- .../interfaces/ip/Ipv4NeighbourCustomizerTest.java | 112 +++++++-------- .../ip/SubInterfaceIpv4AddressCustomizerTest.java | 143 ++++++++++++++++++++ .../interfacesstate/ip/Ipv4CustomizerTest.java | 44 ++++++ 12 files changed, 951 insertions(+), 77 deletions(-) create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/InterfaceCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/L2CustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/RoutingCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceL2CustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/ip/Ipv4CustomizerTest.java diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java index 39e328a9e..baccf619f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java @@ -176,7 +176,7 @@ public final class InterfacesWriterFactory implements WriterFactory { SubinterfaceAugmentationWriterFactory.SUB_IFC_ID); // Proxy Arp (execute after specific interface customizers) registry.addAfter( - new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp, ifcNamingContext)), + new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp)), specificIfcTypes); // ACL (execute after classify table and session writers) // also handles L2Acl, Ip4Acl and Ip6Acl: diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizer.java index 002cc4c77..229902cdb 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizer.java @@ -20,7 +20,6 @@ import com.google.common.net.InetAddresses; import io.fd.honeycomb.translate.spi.write.WriterCustomizer; import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.translate.v3po.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import java.net.InetAddress; @@ -37,15 +36,12 @@ import org.openvpp.jvpp.core.future.FutureJVppCore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - public class ProxyArpCustomizer extends FutureJVppCustomizer implements WriterCustomizer, JvppReplyConsumer { private static final Logger LOG = LoggerFactory.getLogger(ProxyArpCustomizer.class); - private final NamingContext interfaceContext; - public ProxyArpCustomizer(final FutureJVppCore vppApi, final NamingContext interfaceContext) { + public ProxyArpCustomizer(final FutureJVppCore vppApi) { super(vppApi); - this.interfaceContext = interfaceContext; } @Override @@ -54,10 +50,10 @@ public class ProxyArpCustomizer extends FutureJVppCustomizer implements WriterCu final String swIfName = id.firstKeyOf(Interface.class).getName(); try { - setProxyArp(id, swIfName, dataAfter, writeContext, (byte) 1 /* 1 is add */); + setProxyArp(id, swIfName, dataAfter, (byte) 1 /* 1 is add */); } catch (VppBaseCallException e) { LOG.error("Failed to set Proxy ARP settings: {}, for interface: {}", dataAfter, swIfName); - throw new WriteFailedException(id, dataAfter.toString(), e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); } } @@ -75,16 +71,15 @@ public class ProxyArpCustomizer extends FutureJVppCustomizer implements WriterCu final String swIfName = id.firstKeyOf(Interface.class).getName(); try { - setProxyArp(id, swIfName, dataBefore, writeContext, (byte) 0 /* 0 is delete */); + setProxyArp(id, swIfName, dataBefore, (byte) 0 /* 0 is delete */); } catch (VppBaseCallException e) { LOG.debug("Failed to delete Proxy ARP settings: {}, for interface: {}", dataBefore, swIfName); throw new WriteFailedException.DeleteFailedException(id, e); } } - private void setProxyArp(InstanceIdentifier id, String swIfName, ProxyArp proxyArp, WriteContext - writeContext, byte operation) throws VppBaseCallException, WriteFailedException { - + private void setProxyArp(InstanceIdentifier id, String swIfName, ProxyArp proxyArp, byte operation) + throws VppBaseCallException, WriteFailedException { LOG.debug("Setting Proxy ARP settings for interface: {}", swIfName); final InetAddress srcAddress = InetAddresses.forString(getv4AddressString(proxyArp.getLowAddr())); final InetAddress dstAddress = InetAddresses.forString(getv4AddressString(proxyArp.getHighAddr())); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/InterfaceCustomizerTest.java new file mode 100644 index 000000000..fc3dd8379 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/InterfaceCustomizerTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.ByteDataTranslator; +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.VppBaseCallException; +import org.openvpp.jvpp.core.dto.SwInterfaceSetFlags; +import org.openvpp.jvpp.core.dto.SwInterfaceSetFlagsReply; + +public class InterfaceCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator { + private static final String IFACE_CTX_NAME = "interface-ctx"; + private static final String IF_NAME = "eth1"; + private static final int IF_INDEX = 1; + + private InterfaceCustomizer customizer; + private InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)); + + @Override + protected void setUp() throws Exception { + customizer = new InterfaceCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME)); + defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME); + } + + @Test + public void testWrite() throws WriteFailedException { + final boolean enabled = true; + when(api.swInterfaceSetFlags(any())).thenReturn(future(new SwInterfaceSetFlagsReply())); + customizer.writeCurrentAttributes(IID, iface(enabled), writeContext); + verify(api).swInterfaceSetFlags(expectedRequest(enabled)); + } + + @Test + public void testWriteFailed() { + final boolean enabled = false; + when(api.swInterfaceSetFlags(any())).thenReturn(failedFuture()); + try { + customizer.writeCurrentAttributes(IID, iface(enabled), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceSetFlags(expectedRequest(enabled)); + return; + } + fail("WriteFailedException expected"); + } + + @Test + public void testUpdate() throws WriteFailedException { + when(api.swInterfaceSetFlags(any())).thenReturn(future(new SwInterfaceSetFlagsReply())); + customizer.updateCurrentAttributes(IID, iface(false), iface(true), writeContext); + verify(api).swInterfaceSetFlags(expectedRequest(true)); + } + + @Test + public void testUpdateFailed() { + when(api.swInterfaceSetFlags(any())).thenReturn(failedFuture()); + try { + customizer.updateCurrentAttributes(IID, iface(false), iface(true), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceSetFlags(expectedRequest(true)); + return; + } + fail("WriteFailedException expected"); + } + + @Test + public void testDelete() throws WriteFailedException { + customizer.deleteCurrentAttributes(IID, mock(Interface.class), writeContext); + verifyZeroInteractions(api); + } + + private Interface iface(final boolean enabled) { + return new InterfaceBuilder().setName(IF_NAME).setEnabled(enabled).build(); + } + + private SwInterfaceSetFlags expectedRequest(final boolean enabled) { + final SwInterfaceSetFlags request = new SwInterfaceSetFlags(); + request.deleted = 0; + request.adminUpDown = booleanToByte(enabled); + request.linkUpDown = booleanToByte(enabled); + request.swIfIndex = IF_INDEX; + return request; + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/L2CustomizerTest.java new file mode 100644 index 000000000..7f9ba1119 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/L2CustomizerTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.ByteDataTranslator; +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.XconnectBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.XconnectBasedBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.VppBaseCallException; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2Bridge; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2BridgeReply; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2Xconnect; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2XconnectReply; + +public class L2CustomizerTest extends WriterCustomizerTest implements ByteDataTranslator { + private static final String IFACE_CTX_NAME = "interface-ctx"; + private static final String BD_CTX_NAME = "bd-ctx"; + private static final String IF1_NAME = "eth1"; + private static final int IF1_INDEX = 1; + private static final String IF2_NAME = "eth2"; + private static final int IF2_INDEX = 2; + private static final InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF1_NAME)) + .augmentation(VppInterfaceAugmentation.class).child(L2.class); + private static final String BD_NAME = "test_bd"; + private static final int BD_INDEX = 13; + + private L2Customizer customizer; + + @Override + protected void setUp() throws Exception { + customizer = new L2Customizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME), + new NamingContext("bdPrefix", BD_CTX_NAME)); + defineMapping(mappingContext, IF1_NAME, IF1_INDEX, IFACE_CTX_NAME); + defineMapping(mappingContext, IF2_NAME, IF2_INDEX, IFACE_CTX_NAME); + defineMapping(mappingContext, BD_NAME, BD_INDEX, BD_CTX_NAME); + } + + @Test + public void testWrite() throws WriteFailedException { + when(api.swInterfaceSetL2Xconnect(any())).thenReturn(future(new SwInterfaceSetL2XconnectReply())); + customizer.writeCurrentAttributes(IID, l2(xconnectBased()), writeContext); + verify(api).swInterfaceSetL2Xconnect(xconnectRequest(true)); + } + + @Test + public void testWriteFailed() { + when(api.swInterfaceSetL2Bridge(any())).thenReturn(failedFuture()); + try { + customizer.writeCurrentAttributes(IID, l2(bridgeBased(false)), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(false, true)); + return; + } + fail("WriteFailedException expected"); + } + + @Test + public void testUpdate() throws WriteFailedException { + when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply())); + customizer.updateCurrentAttributes(IID, l2(bridgeBased(false)), l2(bridgeBased(true)), writeContext); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(true, true)); + } + + @Test + public void testDelete() throws WriteFailedException { + when(api.swInterfaceSetL2Xconnect(any())).thenReturn(future(new SwInterfaceSetL2XconnectReply())); + customizer.deleteCurrentAttributes(IID, l2(xconnectBased()), writeContext); + verify(api).swInterfaceSetL2Xconnect(xconnectRequest(false)); + } + + @Test + public void testDeleteFailed() { + when(api.swInterfaceSetL2Bridge(any())).thenReturn(failedFuture()); + try { + customizer.deleteCurrentAttributes(IID, l2(bridgeBased(true)), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(true, false)); + return; + } + fail("WriteFailedException expected"); + } + + private XconnectBased xconnectBased() { + return new XconnectBasedBuilder().setXconnectOutgoingInterface(IF2_NAME).build(); + } + + private SwInterfaceSetL2Xconnect xconnectRequest(final boolean enable) { + final SwInterfaceSetL2Xconnect request = new SwInterfaceSetL2Xconnect(); + request.rxSwIfIndex = IF1_INDEX; + request.txSwIfIndex = IF2_INDEX; + request.enable = booleanToByte(enable); + return request; + } + + private BridgeBased bridgeBased(final boolean bvi) { + return new BridgeBasedBuilder().setBridgedVirtualInterface(bvi) + .setBridgeDomain(BD_NAME).setSplitHorizonGroup((short) 123).build(); + } + + private SwInterfaceSetL2Bridge bridgeRequest(final boolean bvi, final boolean enable) { + final SwInterfaceSetL2Bridge request = new SwInterfaceSetL2Bridge(); + request.bdId = BD_INDEX; + request.rxSwIfIndex = IF1_INDEX; + request.bvi = booleanToByte(bvi); + request.enable = booleanToByte(enable); + request.shg = 123; + return request; + } + + + private L2 l2(final Interconnection interconnection) { + return new L2Builder().setInterconnection(interconnection).build(); + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizerTest.java index caac8a37b..81561789d 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ProxyArpCustomizerTest.java @@ -16,33 +16,78 @@ package io.fd.honeycomb.translate.v3po.interfaces; -import static org.mockito.Mockito.mock; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; -import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.util.ByteDataTranslator; import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ProxyArp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ProxyArpBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.core.dto.ProxyArpAddDel; +import org.openvpp.jvpp.core.dto.ProxyArpAddDelReply; -public class ProxyArpCustomizerTest extends WriterCustomizerTest { +public class ProxyArpCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator { + private static final String IF_NAME = "eth1"; private ProxyArpCustomizer customizer; @Override public void setUp() throws Exception { - customizer = new ProxyArpCustomizer(api, new NamingContext("generatedSubInterfaceName", "test-instance")); + customizer = new ProxyArpCustomizer(api); + } + + @Test + public void testWrite() throws WriteFailedException { + when(api.proxyArpAddDel(any())).thenReturn(future(new ProxyArpAddDelReply())); + customizer.writeCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext); + verify(api).proxyArpAddDel(expectedRequest(true)); + } + + @Test(expected = WriteFailedException.class) + public void testWriteFailed() throws WriteFailedException { + when(api.proxyArpAddDel(any())).thenReturn(failedFuture()); + customizer.writeCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext); } @Test(expected = WriteFailedException.UpdateFailedException.class) - public void testUpdate() throws Exception { - final ProxyArp dataBefore = mock(ProxyArp.class); - final ProxyArp dataAfter = mock(ProxyArp.class); - customizer.updateCurrentAttributes(getProxyArpId("eth0"), dataBefore, dataAfter, writeContext); + public void testUpdate() throws WriteFailedException.UpdateFailedException { + customizer.updateCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), proxyArp(), writeContext); + } + + @Test + public void testDelete() throws WriteFailedException { + when(api.proxyArpAddDel(any())).thenReturn(future(new ProxyArpAddDelReply())); + customizer.deleteCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext); + verify(api).proxyArpAddDel(expectedRequest(false)); + } + + @Test(expected = WriteFailedException.DeleteFailedException.class) + public void testDeleteFailed() throws WriteFailedException { + when(api.proxyArpAddDel(any())).thenReturn(failedFuture()); + customizer.deleteCurrentAttributes(getProxyArpId(IF_NAME), proxyArp(), writeContext); + } + + private ProxyArp proxyArp() { + return new ProxyArpBuilder().setVrfId(123L).setHighAddr(new Ipv4AddressNoZone("10.1.1.2")) + .setLowAddr(new Ipv4AddressNoZone("10.1.1.1")).build(); + } + + private ProxyArpAddDel expectedRequest(final boolean isAdd) { + final ProxyArpAddDel request = new ProxyArpAddDel(); + request.isAdd = booleanToByte(isAdd); + request.vrfId = 123; + request.lowAddress = new byte[]{10,1,1,1}; + request.hiAddress = new byte[]{10,1,1,2}; + return request; } private InstanceIdentifier getProxyArpId(final String eth0) { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/RoutingCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/RoutingCustomizerTest.java new file mode 100644 index 000000000..d0db97f66 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/RoutingCustomizerTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.RoutingBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.core.dto.SwInterfaceSetTable; +import org.openvpp.jvpp.core.dto.SwInterfaceSetTableReply; + +public class RoutingCustomizerTest extends WriterCustomizerTest { + private static final String IFACE_CTX_NAME = "interface-ctx"; + private static final String IF_NAME = "eth1"; + private static final int IF_INDEX = 1; + private static final InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)) + .augmentation(VppInterfaceAugmentation.class).child(Routing.class); + + private RoutingCustomizer customizer; + + @Override + protected void setUp() throws Exception { + customizer = new RoutingCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME)); + defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME); + } + + @Test + public void testWrite() throws WriteFailedException { + final int vrfId = 123; + when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply())); + customizer.writeCurrentAttributes(IID, routing(vrfId), writeContext); + verify(api).swInterfaceSetTable(expectedRequest(vrfId)); + } + + @Test(expected = WriteFailedException.CreateFailedException.class) + public void testWriteFailed() throws WriteFailedException { + when(api.swInterfaceSetTable(any())).thenReturn(failedFuture()); + customizer.writeCurrentAttributes(IID, routing(213), writeContext); + } + + @Test + public void testUpdate() throws WriteFailedException { + when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply())); + customizer.updateCurrentAttributes(IID, routing(123L), null, writeContext); + verifyZeroInteractions(api); + } + + @Test(expected = WriteFailedException.UpdateFailedException.class) + public void testUpdateFailed() throws WriteFailedException { + when(api.swInterfaceSetTable(any())).thenReturn(failedFuture()); + customizer.updateCurrentAttributes(IID, routing(123L), routing(321L), writeContext); + } + + @Test + public void testDelete() throws WriteFailedException { + customizer.deleteCurrentAttributes(IID, routing(123), writeContext); + verifyZeroInteractions(api); + } + + private Routing routing(final long vrfId) { + return new RoutingBuilder().setVrfId(vrfId).build(); + } + + private SwInterfaceSetTable expectedRequest(final int vrfId) { + final SwInterfaceSetTable request = new SwInterfaceSetTable(); + request.isIpv6 = 0; + request.swIfIndex = IF_INDEX; + request.vrfId = vrfId; + return request; + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizerTest.java new file mode 100644 index 000000000..779cdc6a3 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizerTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4AclBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6AclBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubinterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.AclBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.core.dto.InputAclSetInterface; +import org.openvpp.jvpp.core.dto.InputAclSetInterfaceReply; + +public class SubInterfaceAclCustomizerTest extends WriterCustomizerTest { + private static final String IFC_TEST_INSTANCE = "ifc-test-instance"; + private static final String IF_NAME = "local0"; + private static final int IF_INDEX = 1; + private static final String SUBIF_NAME = "local0.0"; + private static final int SUBIF_INDEX = 11; + private static final long SUBIF_ID = 0; + private static final String TABLE_NAME = "table0"; + private static final int TABLE_INDEX = 123; + + private static final InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation( + SubinterfaceAugmentation.class).child(SubInterfaces.class) + .child(SubInterface.class, new SubInterfaceKey(SUBIF_ID)).child(Acl.class); + + @Mock + private VppClassifierContextManager classifyTableContext; + + private SubInterfaceAclCustomizer customizer; + + @Override + protected void setUp() throws Exception { + customizer = new SubInterfaceAclCustomizer(api, new NamingContext("prefix", IFC_TEST_INSTANCE), + classifyTableContext); + defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE); + defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE); + when(classifyTableContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX); + } + + @Test + public void testCreate() throws WriteFailedException { + when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply())); + customizer.writeCurrentAttributes(IID, ip4Acl(), writeContext); + verify(api).inputAclSetInterface(expectedIp4AclRequest()); + } + + @Test(expected = WriteFailedException.CreateFailedException.class) + public void testCreateFailed() throws WriteFailedException { + when(api.inputAclSetInterface(any())).thenReturn(failedFuture()); + customizer.writeCurrentAttributes(IID, ip4Acl(), writeContext); + } + + @Test(expected = UnsupportedOperationException.class) + public void testUpdate() throws WriteFailedException { + customizer.updateCurrentAttributes(IID, ip4Acl(), ip6Acl(), writeContext); + } + + @Test + public void testDelete() throws Exception { + when(api.inputAclSetInterface(any())).thenReturn(future(new InputAclSetInterfaceReply())); + customizer.deleteCurrentAttributes(IID, ip6Acl(), writeContext); + verify(api).inputAclSetInterface(expectedIp6AclRequest()); + } + + @Test(expected = WriteFailedException.DeleteFailedException.class) + public void testDeleteFailed() throws WriteFailedException { + when(api.inputAclSetInterface(any())).thenReturn(failedFuture()); + customizer.deleteCurrentAttributes(IID, ip4Acl(), writeContext); + } + + private Acl ip4Acl() { + final AclBuilder builder = new AclBuilder(); + final Ip4Acl acl = new Ip4AclBuilder().setClassifyTable(TABLE_NAME).build(); + builder.setIp4Acl(acl); + return builder.build(); + } + + private InputAclSetInterface expectedIp4AclRequest() { + final InputAclSetInterface request = new InputAclSetInterface(); + request.isAdd = 1; + request.l2TableIndex = -1; + request.ip4TableIndex = TABLE_INDEX; + request.ip6TableIndex = -1; + request.swIfIndex = SUBIF_INDEX; + return request; + } + + private Acl ip6Acl() { + final AclBuilder builder = new AclBuilder(); + final Ip6Acl acl = new Ip6AclBuilder().setClassifyTable(TABLE_NAME).build(); + builder.setIp6Acl(acl); + return builder.build(); + } + + private InputAclSetInterface expectedIp6AclRequest() { + final InputAclSetInterface request = new InputAclSetInterface(); + request.isAdd = 0; + request.l2TableIndex = -1; + request.ip4TableIndex = -1; + request.ip6TableIndex = TABLE_INDEX; + request.swIfIndex = SUBIF_INDEX; + return request; + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceL2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceL2CustomizerTest.java new file mode 100644 index 000000000..0fa380e6b --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceL2CustomizerTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.ByteDataTranslator; +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubinterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2Builder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2Bridge; +import org.openvpp.jvpp.core.dto.SwInterfaceSetL2BridgeReply; + +public class SubInterfaceL2CustomizerTest extends WriterCustomizerTest implements ByteDataTranslator { + private static final String IFACE_CTX_NAME = "interface-ctx"; + private static final String IF_NAME = "local0"; + private static final int IF_INDEX = 1; + private static final String SUBIF_NAME = "local0.0"; + private static final int SUBIF_INDEX = 11; + private static final long SUBIF_ID = 0; + + private static final InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation( + SubinterfaceAugmentation.class).child(SubInterfaces.class) + .child(SubInterface.class, new SubInterfaceKey(SUBIF_ID)).child(L2.class); + + + private static final String BD_CTX_NAME = "bd-ctx"; + private static final String BD_NAME = "test_bd"; + private static final int BD_INDEX = 13; + + private SubInterfaceL2Customizer customizer; + + @Override + protected void setUp() throws Exception { + customizer = new SubInterfaceL2Customizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME), + new NamingContext("bdPrefix", BD_CTX_NAME)); + defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME); + defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFACE_CTX_NAME); + defineMapping(mappingContext, BD_NAME, BD_INDEX, BD_CTX_NAME); + } + + @Test + public void testWrite() throws WriteFailedException { + final boolean bvi = true; + when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply())); + customizer.writeCurrentAttributes(IID, l2(bvi), writeContext); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, true)); + } + + @Test + public void testUpdate() throws WriteFailedException { + final boolean bvi = false; + when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply())); + customizer.updateCurrentAttributes(IID, l2(true), l2(bvi), writeContext); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, true)); + } + + @Test + public void testDelete() throws WriteFailedException { + final boolean bvi = true; + when(api.swInterfaceSetL2Bridge(any())).thenReturn(future(new SwInterfaceSetL2BridgeReply())); + customizer.deleteCurrentAttributes(IID, l2(bvi), writeContext); + verify(api).swInterfaceSetL2Bridge(bridgeRequest(bvi, false)); + } + + private L2 l2(final boolean bvi) { + return new L2Builder().setInterconnection(new BridgeBasedBuilder().setBridgedVirtualInterface(bvi) + .setBridgeDomain(BD_NAME).setSplitHorizonGroup((short) 123).build()).build(); + } + + private SwInterfaceSetL2Bridge bridgeRequest(final boolean bvi, final boolean enable) { + final SwInterfaceSetL2Bridge request = new SwInterfaceSetL2Bridge(); + request.bdId = BD_INDEX; + request.rxSwIfIndex = SUBIF_INDEX; + request.bvi = booleanToByte(bvi); + request.enable = booleanToByte(enable); + request.shg = 123; + return request; + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java index 56430cd46..e3857b9b1 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4AddressCustomizerTest.java @@ -23,6 +23,7 @@ import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -189,6 +190,12 @@ public class Ipv4AddressCustomizerTest extends WriterCustomizerTest { }; } + @Test(expected = WriteFailedException.UpdateFailedException.class) + public void testUpdate() throws Exception { + final Address data = mock(Address.class); + customizer.updateCurrentAttributes(getAddressId(IFACE_NAME), data, data, writeContext); + } + private SwInterfaceAddDelAddress generateSwInterfaceAddDelAddressRequest(final byte[] address, final byte isAdd, final byte prefixLength) { final SwInterfaceAddDelAddress request = new SwInterfaceAddDelAddress(); @@ -241,6 +248,32 @@ public class Ipv4AddressCustomizerTest extends WriterCustomizerTest { fail("WriteFailedException was expec16ted"); } + @Test + public void testNetmaskFailed() { + final int expectedPrefixLength = 1; + final String stringMask = "128.0.0.0"; + final InstanceIdentifier
id = getAddressId(IFACE_NAME); + when(writeContext.readBefore(id)).thenReturn(Optional.absent()); + + Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1")); + Netmask subnet = new NetmaskBuilder().setNetmask(new DottedQuad(stringMask)).build(); + Address data = new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build(); + + defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME); + whenSwInterfaceAddDelAddressThenFailure(); + + try { + customizer.writeCurrentAttributes(id, data, writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1}, + (byte) 1, (byte) expectedPrefixLength)); + return; + } + fail("WriteFailedException was expec16ted"); + + } + private void testSingleNetmask(final int expectedPrefixLength, final String stringMask) throws Exception { final InstanceIdentifier
id = getAddressId(IFACE_NAME); when(writeContext.readBefore(id)).thenReturn(Optional.absent()); @@ -255,7 +288,7 @@ public class Ipv4AddressCustomizerTest extends WriterCustomizerTest { customizer.writeCurrentAttributes(id, data, writeContext); verify(api).swInterfaceAddDelAddress(generateSwInterfaceAddDelAddressRequest(new byte[]{-64, -88, 2, 1}, - (byte) 1, (byte) expectedPrefixLength)); + (byte) 1, (byte) expectedPrefixLength)); } private void testSingleIllegalNetmask(final String stringMask) throws Exception { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java index e9acdbe88..a3fff0858 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/Ipv4NeighbourCustomizerTest.java @@ -16,20 +16,16 @@ package io.fd.honeycomb.translate.v3po.interfaces.ip; -import static org.junit.Assert.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; - -import com.google.common.io.BaseEncoding; import io.fd.honeycomb.translate.v3po.util.Ipv4Translator; import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.write.WriteFailedException; import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; -import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; @@ -41,6 +37,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.VppBaseCallException; import org.openvpp.jvpp.core.dto.IpNeighborAddDel; import org.openvpp.jvpp.core.dto.IpNeighborAddDelReply; @@ -49,70 +46,75 @@ public class Ipv4NeighbourCustomizerTest extends WriterCustomizerTest implements private static final String IFC_CTX_NAME = "ifc-test-instance"; private static final String IFACE_NAME = "parent"; private static final int IFACE_ID = 5; + private static final InstanceIdentifier IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) + .augmentation(Interface1.class).child(Ipv4.class).child(Neighbor.class); - private ArgumentCaptor requestCaptor; private Ipv4NeighbourCustomizer customizer; - @Before - public void init() { + @Override + public void setUp() { defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_CTX_NAME); customizer = new Ipv4NeighbourCustomizer(api, new NamingContext("prefix", IFC_CTX_NAME)); - - requestCaptor = ArgumentCaptor.forClass(IpNeighborAddDel.class); - when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply())); } @Test public void testWriteCurrentAttributes() throws WriteFailedException { + when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply())); + customizer.writeCurrentAttributes(IID, getData(), writeContext); + verify(api).ipNeighborAddDel(getExpectedRequest(true)); + } - InterfaceKey intfKey = new InterfaceKey(IFACE_NAME); - - InstanceIdentifier id = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, intfKey) - .augmentation(Interface1.class).child(Ipv4.class).child(Neighbor.class).build(); - - Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1")); - PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22"); - - Neighbor data = new NeighborBuilder().setIp(noZoneIp).setLinkLayerAddress(mac).build(); - - customizer.writeCurrentAttributes(id, data, writeContext); - - verify(api, times(1)).ipNeighborAddDel(requestCaptor.capture()); - - IpNeighborAddDel request = requestCaptor.getValue(); - - assertEquals(0, request.isIpv6); - assertEquals(1, request.isAdd); - assertEquals(1, request.isStatic); - assertEquals("1.2.168.192", arrayToIpv4AddressNoZone(request.dstAddress).getValue()); - assertEquals("aabbccee1122", BaseEncoding.base16().lowerCase().encode(request.macAddress)); - assertEquals(5, request.swIfIndex); + @Test + public void testWriteCurrentAttributesFailed() { + when(api.ipNeighborAddDel(any())).thenReturn(failedFuture()); + try { + customizer.writeCurrentAttributes(IID, getData(), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).ipNeighborAddDel(getExpectedRequest(true)); + return; + } + fail("WriteFailedException expected"); + } + @Test(expected = UnsupportedOperationException.class) + public void testUpdateCurrentAttributes() throws WriteFailedException { + customizer.updateCurrentAttributes(IID, getData(), getData(), writeContext); } @Test public void testDeleteCurrentAttributes() throws WriteFailedException { - InterfaceKey intfKey = new InterfaceKey(IFACE_NAME); - - InstanceIdentifier id = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, intfKey) - .augmentation(Interface1.class).child(Ipv4.class).child(Neighbor.class).build(); - - Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1")); - PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22"); - - Neighbor data = new NeighborBuilder().setIp(noZoneIp).setLinkLayerAddress(mac).build(); - - customizer.deleteCurrentAttributes(id, data, writeContext); - - verify(api, times(1)).ipNeighborAddDel(requestCaptor.capture()); - - IpNeighborAddDel request = requestCaptor.getValue(); + when(api.ipNeighborAddDel(any())).thenReturn(future(new IpNeighborAddDelReply())); + customizer.deleteCurrentAttributes(IID, getData(), writeContext); + verify(api).ipNeighborAddDel(getExpectedRequest(false)); + } - assertEquals(0, request.isIpv6); - assertEquals(0, request.isAdd); - assertEquals(1, request.isStatic); - assertEquals("1.2.168.192", arrayToIpv4AddressNoZone(request.dstAddress).getValue()); - assertEquals("aabbccee1122", BaseEncoding.base16().lowerCase().encode(request.macAddress)); - assertEquals(5, request.swIfIndex); + @Test + public void testDeleteCurrentAttributesFailed() { + when(api.ipNeighborAddDel(any())).thenReturn(failedFuture()); + try { + customizer.deleteCurrentAttributes(IID, getData(), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).ipNeighborAddDel(getExpectedRequest(false)); + return; + } + fail("WriteFailedException expected"); } + private Neighbor getData() { + final Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1")); + final PhysAddress mac = new PhysAddress("aa:bb:cc:ee:11:22"); + return new NeighborBuilder().setIp(noZoneIp).setLinkLayerAddress(mac).build(); + } + private IpNeighborAddDel getExpectedRequest(final boolean isAdd) { + final IpNeighborAddDel request = new IpNeighborAddDel(); + request.isIpv6 = 0; + request.isAdd = booleanToByte(isAdd); + request.isStatic = 1; + request.dstAddress = new byte[] {(byte) 192, (byte) 168, 2, 1}; + request.macAddress = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xee, 0x11, 0x22}; + request.swIfIndex = IFACE_ID; + return request; + } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java new file mode 100644 index 000000000..b5cb009ed --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/ip/SubInterfaceIpv4AddressCustomizerTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfaces.ip; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.translate.v3po.util.ByteDataTranslator; +import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubinterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.Ipv4; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.Address; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.AddressBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.address.Subnet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.address.subnet.Netmask; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.address.subnet.NetmaskBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLength; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.address.subnet.PrefixLengthBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.VppBaseCallException; +import org.openvpp.jvpp.core.dto.SwInterfaceAddDelAddress; +import org.openvpp.jvpp.core.dto.SwInterfaceAddDelAddressReply; + +public class SubInterfaceIpv4AddressCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator { + + private static final String IFC_CTX_NAME = "ifc-test-instance"; + private static final String IFACE_NAME = "eth0"; + private static final int IFACE_INDEX = 0; + private static final String SUBIF_NAME = "eth0.1"; + private static final long SUBIF_ID = 1; + private static final int SUBIF_INDEX = 123; + private static final InstanceIdentifier
IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME)) + .augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class) + .child(SubInterface.class, new SubInterfaceKey(SUBIF_ID)).child(Ipv4.class).child(Address.class); + + private SubInterfaceIpv4AddressCustomizer customizer; + + @Override + protected void setUp() { + customizer = new SubInterfaceIpv4AddressCustomizer(api, new NamingContext("prefix", IFC_CTX_NAME)); + defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, IFC_CTX_NAME); + defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFC_CTX_NAME); + } + + @Test + public void testWrite() throws WriteFailedException { + when(api.swInterfaceAddDelAddress(any())).thenReturn(future(new SwInterfaceAddDelAddressReply())); + customizer.writeCurrentAttributes(IID, address(prefixLength()), writeContext); + verify(api).swInterfaceAddDelAddress(expectedRequest(true)); + } + + @Test + public void testWriteFailed() { + when(api.swInterfaceAddDelAddress(any())).thenReturn(failedFuture()); + try { + customizer.writeCurrentAttributes(IID, address(prefixLength()), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceAddDelAddress(expectedRequest(true)); + return; + } + fail("WriteFailedException expected"); + } + + @Test + public void testDelete() throws WriteFailedException { + when(api.swInterfaceAddDelAddress(any())).thenReturn(future(new SwInterfaceAddDelAddressReply())); + customizer.deleteCurrentAttributes(IID, address(netmask()), writeContext); + verify(api).swInterfaceAddDelAddress(expectedRequest(false)); + } + + @Test + public void testDeleteFailed() { + when(api.swInterfaceAddDelAddress(any())).thenReturn(failedFuture()); + try { + customizer.deleteCurrentAttributes(IID, address(netmask()), writeContext); + } catch (WriteFailedException e) { + assertTrue(e.getCause() instanceof VppBaseCallException); + verify(api).swInterfaceAddDelAddress(expectedRequest(false)); + return; + } + fail("WriteFailedException expected"); + } + + private SwInterfaceAddDelAddress expectedRequest(boolean isAdd) { + final SwInterfaceAddDelAddress request = new SwInterfaceAddDelAddress(); + request.isAdd = booleanToByte(isAdd); + request.swIfIndex = SUBIF_INDEX; + request.isIpv6 = 0; + request.delAll = 0; + request.addressLength = 24; + request.address = new byte[] {(byte) 192, (byte) 168, 2, 1}; + return request; + } + + @Test(expected = WriteFailedException.UpdateFailedException.class) + public void testUpdate() throws Exception { + final Address address = address(prefixLength()); + customizer.updateCurrentAttributes(IID, address, address, writeContext); + } + + private Address address(final Subnet subnet) { + final Ipv4AddressNoZone noZoneIp = new Ipv4AddressNoZone(new Ipv4Address("192.168.2.1")); + return new AddressBuilder().setIp(noZoneIp).setSubnet(subnet).build(); + } + + private PrefixLength prefixLength() { + return new PrefixLengthBuilder().setPrefixLength(new Integer(24).shortValue()).build(); + } + + private Netmask netmask() { + return new NetmaskBuilder().setNetmask(new DottedQuad("255.255.255.0")).build(); + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/ip/Ipv4CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/ip/Ipv4CustomizerTest.java new file mode 100644 index 000000000..f536a37eb --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/ip/Ipv4CustomizerTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * 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 io.fd.honeycomb.translate.v3po.interfacesstate.ip; + +import static org.mockito.Mockito.verifyZeroInteractions; + +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.vpp.test.read.ReaderCustomizerTest; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4Builder; + +public class Ipv4CustomizerTest extends ReaderCustomizerTest { + + public Ipv4CustomizerTest() { + super(Ipv4.class, Interface2Builder.class); + } + + @Test + public void testReadCurrentAttributes() throws Exception { + customizer.readCurrentAttributes(null, null, ctx); + verifyZeroInteractions(api); + } + + @Override + protected ReaderCustomizer initCustomizer() { + return new Ipv4Customizer(api); + } +} \ No newline at end of file -- cgit 1.2.3-korg