summaryrefslogtreecommitdiffstats
path: root/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write
diff options
context:
space:
mode:
Diffstat (limited to 'v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write')
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizerTest.java87
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizerTest.java112
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketValidatorTest.java88
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetCustomizerTest.java82
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetValidatorTest.java76
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreCustomizerTest.java188
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreValidatorTest.java111
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizerTest.java125
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizerTest.java115
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidatorTest.java146
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceTypeTestUtils.java40
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizerTest.java55
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidatorTest.java82
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceValidatorTest.java85
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizerTest.java74
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/L2CustomizerTest.java151
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizerTest.java105
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/RewriteCustomizerTest.java197
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizerTest.java256
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2CustomizerTest.java110
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizerTest.java148
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidatorTest.java123
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizerTest.java61
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidatorTest.java80
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidatorTest.java85
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/TapV2CustomizerTest.java162
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizerTest.java205
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserValidatorTest.java79
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanCustomizerTest.java223
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizerTest.java210
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidatorTest.java151
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanValidatorTest.java142
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizerTest.java193
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidatorTest.java189
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesCustomizerTest.java113
-rw-r--r--v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesValidatorTest.java115
36 files changed, 4564 insertions, 0 deletions
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizerTest.java
new file mode 100644
index 000000000..bc7b6164a
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AbstractUnnumberedCustomizerTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.jvpp.core.dto.SwInterfaceSetUnnumbered;
+import io.fd.jvpp.core.dto.SwInterfaceSetUnnumberedReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.UnnumberedBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+abstract class AbstractUnnumberedCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+
+ protected static final String IFC_CTX_NAME = "ifc-ctx";
+ private AbstractUnnumberedCustomizer customizer;
+ private static final String TARGET_IFC0_NAME = "eth0";
+ private static final int TARGET_IFC0_ID = 0;
+ private static final String TARGET_IFC1_NAME = "eth1";
+ private static final int TARGET_IFC1_ID = 1;
+
+
+ @Override
+ public void setUpTest() {
+ customizer = getCustomizer();
+ defineMapping(mappingContext, TARGET_IFC0_NAME, TARGET_IFC0_ID, IFC_CTX_NAME);
+ defineMapping(mappingContext, TARGET_IFC1_NAME, TARGET_IFC1_ID, IFC_CTX_NAME);
+ defineMapping(mappingContext, getUnnumberedIfcName(), getUnnumberedIfcId(), IFC_CTX_NAME);
+ when(api.swInterfaceSetUnnumbered(any())).thenReturn(future(new SwInterfaceSetUnnumberedReply()));
+ }
+
+ protected abstract int getUnnumberedIfcId();
+
+ protected abstract String getUnnumberedIfcName();
+
+ protected abstract InstanceIdentifier<Unnumbered> getUnnumberedIfcIId();
+
+ protected abstract AbstractUnnumberedCustomizer getCustomizer();
+
+ @Test
+ public void testWrite() throws Exception {
+ final Unnumbered data = new UnnumberedBuilder().setUse(TARGET_IFC0_NAME).build();
+ customizer.writeCurrentAttributes(getUnnumberedIfcIId(), data, writeContext);
+ verify(api).swInterfaceSetUnnumbered(expectedRequest(true, TARGET_IFC0_ID));
+ }
+ @Test
+ public void testUpdate() throws Exception {
+ final Unnumbered before = new UnnumberedBuilder().setUse(TARGET_IFC0_NAME).build();
+ final Unnumbered after = new UnnumberedBuilder().setUse(TARGET_IFC1_NAME).build();
+ customizer.updateCurrentAttributes(getUnnumberedIfcIId(), before, after, writeContext);
+ verify(api).swInterfaceSetUnnumbered(expectedRequest(true, TARGET_IFC1_ID));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final Unnumbered data = new UnnumberedBuilder().setUse(TARGET_IFC0_NAME).build();
+ customizer.deleteCurrentAttributes(getUnnumberedIfcIId(), data, writeContext);
+ verify(api).swInterfaceSetUnnumbered(expectedRequest(false, TARGET_IFC0_ID));
+ }
+
+ private SwInterfaceSetUnnumbered expectedRequest(final boolean isAdd, int swIfIntex) {
+ final SwInterfaceSetUnnumbered request = new SwInterfaceSetUnnumbered();
+ request.swIfIndex = swIfIntex;
+ request.unnumberedSwIfIndex = getUnnumberedIfcId();
+ request.isAdd = booleanToByte(isAdd);
+ return request;
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizerTest.java
new file mode 100644
index 000000000..33125f182
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketCustomizerTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.AfPacketCreate;
+import io.fd.jvpp.core.dto.AfPacketCreateReply;
+import io.fd.jvpp.core.dto.AfPacketDelete;
+import io.fd.jvpp.core.dto.AfPacketDeleteReply;
+import java.nio.charset.StandardCharsets;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacketBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final int IFACE_ID = 1;
+ private static final String IFACE_NAME = "veth1";
+ private static final InstanceIdentifier<AfPacket> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(AfPacket.class);
+ private AfPacketCustomizer customizer;
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.AfPacket.class);
+ customizer = new AfPacketCustomizer(api, new NamingContext("generatedInterfaceName", IFC_TEST_INSTANCE));
+
+ final AfPacketCreateReply createReply = new AfPacketCreateReply();
+ createReply.swIfIndex = IFACE_ID;
+ when(api.afPacketCreate(any())).thenReturn(future(createReply));
+ when(api.afPacketDelete(any())).thenReturn(future(new AfPacketDeleteReply()));
+ }
+
+ @Test
+ public void testWriteRandomMac() throws WriteFailedException {
+ final AfPacketCreate expectedCreateRequest = new AfPacketCreate();
+ expectedCreateRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+ expectedCreateRequest.useRandomHwAddr = 1;
+ expectedCreateRequest.hwAddr = new byte[6];
+
+ customizer.writeCurrentAttributes(ID, afPacket(), writeContext);
+
+ verify(api).afPacketCreate(expectedCreateRequest);
+ verify(mappingContext).put(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE), mapping(IFACE_NAME, IFACE_ID).get());
+ }
+
+ @Test
+ public void testWriteExplicitMac() throws WriteFailedException {
+ final AfPacket afPacket = afPacket("01:02:03:04:05:06");
+
+ final AfPacketCreate expectedCreateRequest = new AfPacketCreate();
+ expectedCreateRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+ expectedCreateRequest.useRandomHwAddr = 0;
+ expectedCreateRequest.hwAddr = new byte[] {1, 2, 3, 4, 5, 6};
+
+ customizer.writeCurrentAttributes(ID, afPacket, writeContext);
+
+ verify(api).afPacketCreate(expectedCreateRequest);
+ verify(mappingContext).put(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE), mapping(IFACE_NAME, IFACE_ID).get());
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ final AfPacket afPacket = afPacket("02:03:04:05:06:07");
+ final AfPacketDelete expectedDeleteRequest = new AfPacketDelete();
+ expectedDeleteRequest.hostIfName = IFACE_NAME.getBytes(StandardCharsets.UTF_8);
+
+ customizer.deleteCurrentAttributes(ID, afPacket, writeContext);
+
+ verify(api).afPacketDelete(expectedDeleteRequest);
+ verify(mappingContext).delete(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)));
+ }
+
+ private static AfPacket afPacket() {
+ return new AfPacketBuilder().setHostInterfaceName(IFACE_NAME).build();
+ }
+
+ private static AfPacket afPacket(String mac) {
+ return new AfPacketBuilder().setHostInterfaceName(IFACE_NAME).setMac(new PhysAddress(mac)).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketValidatorTest.java
new file mode 100644
index 000000000..bdc1bdb31
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/AfPacketValidatorTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacketBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketValidatorTest {
+
+ private AfPacketValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private final String IFACE_NAME = "veth1";
+ private final InstanceIdentifier<AfPacket> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(AfPacket.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new AfPacketValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, afPacket(IFACE_NAME), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoHostName() throws CreateValidationFailedException {
+ validator.validateWrite(ID, afPacket(null), writeContext);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWriteFailedLongHostName() throws CreateValidationFailedException {
+ validator.validateWrite(ID,
+ afPacket(IntStream.range(1, 64).boxed().map(i -> i.toString()).collect(Collectors.joining(","))),
+ writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ validator.validateUpdate(ID, afPacket(IFACE_NAME), afPacket(IFACE_NAME), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, afPacket(IFACE_NAME), writeContext);
+ }
+
+ private AfPacket afPacket(String name) {
+ return new AfPacketBuilder().setHostInterfaceName(name).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetCustomizerTest.java
new file mode 100644
index 000000000..2ad687c68
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetCustomizerTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.HwInterfaceSetMtu;
+import io.fd.jvpp.core.dto.HwInterfaceSetMtuReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev180703.EthernetCsmacd;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EthernetCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "eth0";
+ private static final int IF_INDEX = 1;
+ private static final InstanceIdentifier<Ethernet> IF_IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ VppInterfaceAugmentation.class).child(Ethernet.class);
+ private EthernetCustomizer customizer;
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext, EthernetCsmacd.class);
+ customizer = new EthernetCustomizer(api, new NamingContext("ifcintest", IFC_TEST_INSTANCE));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFC_TEST_INSTANCE);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(api.hwInterfaceSetMtu(any())).thenReturn(future(new HwInterfaceSetMtuReply()));
+ final int mtu = 1234;
+ customizer.writeCurrentAttributes(IF_IID, EthernetValidatorTest.ethernet(mtu), writeContext);
+ verify(api).hwInterfaceSetMtu(mtuSetRequest(mtu));
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ when(api.hwInterfaceSetMtu(any())).thenReturn(future(new HwInterfaceSetMtuReply()));
+ final int mtu = 5678;
+ customizer.updateCurrentAttributes(IF_IID, mock(Ethernet.class), EthernetValidatorTest.ethernet(mtu), writeContext);
+ verify(api).hwInterfaceSetMtu(mtuSetRequest(mtu));
+ }
+
+ private HwInterfaceSetMtu mtuSetRequest(final int mtu) {
+ final HwInterfaceSetMtu request = new HwInterfaceSetMtu();
+ request.swIfIndex = IF_INDEX;
+ request.mtu = (short)mtu;
+ return request;
+ }
+
+ @Test(expected = WriteFailedException.class)
+ public void testDelete() throws WriteFailedException {
+ customizer.deleteCurrentAttributes(IF_IID, mock(Ethernet.class), writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetValidatorTest.java
new file mode 100644
index 000000000..1c199d304
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/EthernetValidatorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.EthernetBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EthernetValidatorTest {
+
+ private EthernetValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth0";
+ private static final int IF_MTU = 1234;
+ private static final InstanceIdentifier<Ethernet> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+ VppInterfaceAugmentation.class).child(Ethernet.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new EthernetValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, ethernet(IF_MTU), writeContext);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testWriteFailedNoMTU() throws CreateValidationFailedException {
+ validator.validateWrite(ID, ethernet(null), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ validator.validateUpdate(ID, ethernet(IF_MTU), ethernet(IF_MTU + 1), writeContext);
+ }
+
+ static Ethernet ethernet(final Integer mtu) {
+ final EthernetBuilder ethernet = new EthernetBuilder();
+ ethernet.setMtu(mtu);
+ return ethernet.build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreCustomizerTest.java
new file mode 100644
index 000000000..55f0ab488
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreCustomizerTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.core.dto.GreTunnelAddDel;
+import io.fd.jvpp.core.dto.GreTunnelAddDelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.GreBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GreCustomizerTest extends WriterCustomizerTest implements AddressTranslator {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final byte ADD_GRE = 1;
+ private static final byte DEL_GRE = 0;
+ private final String IFACE_NAME = "eth0";
+ private final int IFACE_ID = 1;
+ private InstanceIdentifier<Gre> id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Gre.class);
+ private GreCustomizer customizer;
+
+ private static Gre generateGre() {
+ final GreBuilder builder = new GreBuilder();
+ builder.setSrc(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.10")));
+ builder.setDst(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.11")));
+ builder.setOuterFibId(Long.valueOf(123));
+ return builder.build();
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.GreTunnel.class);
+ customizer = new GreCustomizer(api, new NamingContext("generateInterfaceNAme", IFC_TEST_INSTANCE));
+ }
+
+ private void whenGreAddDelTunnelThenSuccess() {
+ final GreTunnelAddDelReply reply = new GreTunnelAddDelReply();
+ reply.swIfIndex = IFACE_ID;
+ doReturn(future(reply)).when(api).greTunnelAddDel(any(GreTunnelAddDel.class));
+ }
+
+ private void whenGreAddDelTunnelThenFailure() {
+ doReturn(failedFuture()).when(api).greTunnelAddDel(any(GreTunnelAddDel.class));
+ }
+
+ private GreTunnelAddDel verifyGreAddDelTunnelWasInvoked(final Gre gre) throws VppInvocationException {
+ ArgumentCaptor<GreTunnelAddDel> argumentCaptor = ArgumentCaptor.forClass(GreTunnelAddDel.class);
+ verify(api).greTunnelAddDel(argumentCaptor.capture());
+ final GreTunnelAddDel actual = argumentCaptor.getValue();
+ assertEquals(0, actual.tunnel.isIpv6);
+ assertArrayEquals(ipAddressToArray(gre.getSrc()), actual.tunnel.src.un.getIp4().ip4Address);
+ assertArrayEquals(ipAddressToArray(gre.getDst()), actual.tunnel.dst.un.getIp4().ip4Address);
+ assertEquals(gre.getOuterFibId().intValue(), actual.tunnel.outerFibId);
+ return actual;
+ }
+
+ private void verifyGreAddWasInvoked(final Gre gre) throws VppInvocationException {
+ final GreTunnelAddDel actual = verifyGreAddDelTunnelWasInvoked(gre);
+ assertEquals(ADD_GRE, actual.isAdd);
+ }
+
+ private void verifyGreDeleteWasInvoked(final Gre gre) throws VppInvocationException {
+ final GreTunnelAddDel actual = verifyGreAddDelTunnelWasInvoked(gre);
+ assertEquals(DEL_GRE, actual.isAdd);
+ }
+
+ @Test
+ public void testWriteCurrentAttributes() throws Exception {
+ final Gre gre = generateGre();
+
+ whenGreAddDelTunnelThenSuccess();
+
+ noMappingDefined(mappingContext, IFACE_NAME, IFC_TEST_INSTANCE);
+
+ customizer.writeCurrentAttributes(id, gre, writeContext);
+ verifyGreAddWasInvoked(gre);
+ verify(mappingContext).put(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)),
+ eq(mapping(IFACE_NAME, IFACE_ID).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
+ final Gre gre = generateGre();
+
+ whenGreAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_TEST_INSTANCE);
+
+ customizer.writeCurrentAttributes(id, gre, writeContext);
+ verifyGreAddWasInvoked(gre);
+
+ // Remove the first mapping before putting in the new one
+ verify(mappingContext).delete(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)));
+ verify(mappingContext).put(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)), eq(mapping(IFACE_NAME, IFACE_ID).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesFailed() throws Exception {
+ final Gre gre = generateGre();
+
+ whenGreAddDelTunnelThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, gre, writeContext);
+ } catch (WriteFailedException.CreateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyGreAddWasInvoked(gre);
+ // Mapping not stored due to failure
+ verify(mappingContext, times(0)).put(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)), eq(mapping(
+ IFACE_NAME, 0).get()));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdateCurrentAttributes() throws Exception {
+ customizer.updateCurrentAttributes(id, generateGre(), generateGre(), writeContext);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributes() throws Exception {
+ final Gre gre = generateGre();
+
+ whenGreAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_TEST_INSTANCE);
+
+ customizer.deleteCurrentAttributes(id, gre, writeContext);
+ verifyGreDeleteWasInvoked(gre);
+ verify(mappingContext).delete(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)));
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesaFailed() throws Exception {
+ final Gre gre = generateGre();
+
+ whenGreAddDelTunnelThenFailure();
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, IFC_TEST_INSTANCE);
+
+ try {
+ customizer.deleteCurrentAttributes(id, gre, writeContext);
+ } catch (WriteFailedException.DeleteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyGreDeleteWasInvoked(gre);
+ verify(mappingContext, times(0)).delete(eq(mappingIid(IFACE_NAME, IFC_TEST_INSTANCE)));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreValidatorTest.java
new file mode 100644
index 000000000..d8f460284
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/GreValidatorTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.GreBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GreValidatorTest {
+
+ private GreValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IPV6 = "a::100";
+ private static final String IPV4_1 = "192.168.20.10";
+ private static final String IPV4_2 = "192.168.20.11";
+ private static final Long OUT_FIB_ID = Long.valueOf(123);
+ private static final String IFACE_NAME = "eth0";
+ private static final InstanceIdentifier<Gre> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Gre.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new GreValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateCorrectGre(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedMixedIpv4Ipv6() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateGre(ip4(IPV4_1), ip6(IPV6), OUT_FIB_ID), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoSrcAddr() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateGre(null, ip6(IPV6), OUT_FIB_ID), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoDstAddr() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateGre(ip4(IPV4_1), null, OUT_FIB_ID), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoOutFibId() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateGre(ip4(IPV4_1), ip4(IPV4_2), null), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, generateCorrectGre(), writeContext);
+ }
+
+ private Gre generateCorrectGre() {
+ return generateGre(ip4(IPV4_1), ip4(IPV4_2), OUT_FIB_ID);
+ }
+
+ private Gre generateGre(final IpAddressNoZone srcAddr, final IpAddressNoZone dstAddr, final Long outerFibId) {
+ final GreBuilder builder = new GreBuilder();
+ builder.setSrc(srcAddr);
+ builder.setDst(dstAddr);
+ builder.setOuterFibId(outerFibId);
+ return builder.build();
+ }
+
+ private IpAddressNoZone ip4(String addr) {
+ return new IpAddressNoZone(new Ipv4AddressNoZone(addr));
+ }
+
+ private IpAddressNoZone ip6(String addr) {
+ return new IpAddressNoZone(new Ipv6AddressNoZone(addr));
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizerTest.java
new file mode 100644
index 000000000..c7fd7b970
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceCustomizerTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+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.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlagsReply;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+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 static final InstanceIdentifier<Interface> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME));
+
+ private static final String LOCAL0_IFC_NAME = "local0";
+ private static final InstanceIdentifier<Interface> LOCAL0_IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(LOCAL0_IFC_NAME));
+ private InterfaceCustomizer customizer;
+
+ @Override
+ protected void setUpTest() 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);
+ }
+
+ @Test(expected = WriteFailedException.DeleteFailedException.class)
+ public void testDeleteLocal0() throws WriteFailedException {
+ final Interface ifc = mock(Interface.class);
+ when(ifc.getName()).thenReturn(LOCAL0_IFC_NAME);
+ customizer.deleteCurrentAttributes(LOCAL0_IID, ifc, writeContext);
+ }
+
+ 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.adminUpDown = booleanToByte(enabled);
+ request.swIfIndex = IF_INDEX;
+ return request;
+ }
+} \ No newline at end of file
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizerTest.java
new file mode 100644
index 000000000..4615a600b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingCustomizerTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSetTable;
+import io.fd.jvpp.core.dto.SwInterfaceSetTableReply;
+import java.util.Optional;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingCustomizerTest 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<Routing> IID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Routing.class);
+
+ private InterfaceRoutingCustomizer customizer;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new InterfaceRoutingCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ 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.class)
+ public void testWriteFailed() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ when(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.writeCurrentAttributes(IID, routing(213), writeContext);
+ }
+
+ @Test
+ public void testWriteEmptyIfaceData() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class)))
+ .thenReturn(Optional.of(new InterfaceBuilder().build()));
+ 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.class)
+ public void testUpdateFailed() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ when(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.updateCurrentAttributes(IID, routing(123L), routing(321L), writeContext);
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ when(writeContext.readAfter(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
+ customizer.deleteCurrentAttributes(IID, routing(123), writeContext);
+ verify(api).swInterfaceSetTable(expectedRequest(0));
+ }
+
+ @Test(expected = WriteFailedException.DeleteFailedException.class)
+ public void testDeleteFailed() throws WriteFailedException {
+ when(writeContext.readAfter(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ when(api.swInterfaceSetTable(any())).thenReturn(failedFuture());
+ customizer.deleteCurrentAttributes(IID, routing(123), writeContext);
+ }
+
+ private Routing routing(final long vrfId) {
+ return new RoutingBuilder().setIpv4VrfId(new VniReference(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;
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidatorTest.java
new file mode 100644
index 000000000..7cefb112b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceRoutingValidatorTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.Interface1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.ipv4.AddressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingValidatorTest {
+
+ private InterfaceRoutingValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth1";
+ private static final Long VRF_ID = Long.valueOf(123);
+
+ private static final InstanceIdentifier<Routing> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Routing.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new InterfaceRoutingValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoFrfIds() throws CreateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateWrite(ID, routing(null, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedWithV4Address() throws CreateValidationFailedException {
+ when(writeContext.readBefore(RWUtils.cutId(ID, Interface.class)))
+ .thenReturn(Optional.of(ifaceWithV4Address()));
+ validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedWithV6Address() throws CreateValidationFailedException {
+ when(writeContext.readBefore(RWUtils.cutId(ID, Interface.class)))
+ .thenReturn(Optional.of(ifaceWithV6Address()));
+ validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateUpdate(ID, routing(VRF_ID, true, false),
+ routing(VRF_ID, true, true), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateDelete(ID, routing(VRF_ID, true, false), writeContext);
+ }
+
+ private Routing routing(final Long vrfId, final boolean hasIpv4, final boolean hasIpv6) {
+ VniReference vni = null;
+ if (vrfId != null) {
+ vni = new VniReference(vrfId);
+ }
+
+ RoutingBuilder builder = new RoutingBuilder();
+ if (hasIpv4) {
+ builder.setIpv4VrfId(vni);
+ }
+ if (hasIpv6) {
+ builder.setIpv6VrfId(vni);
+ }
+ return builder.build();
+ }
+
+ private Interface ifaceWithV4Address() {
+ return new InterfaceBuilder()
+ .addAugmentation(Interface1.class, new Interface1Builder()
+ .setIpv4(new Ipv4Builder()
+ .setAddress(Collections.singletonList(new AddressBuilder().build()))
+ .build())
+ .build())
+ .build();
+ }
+
+ private Interface ifaceWithV6Address() {
+ return new InterfaceBuilder()
+ .addAugmentation(Interface1.class, new Interface1Builder()
+ .setIpv6(new Ipv6Builder()
+ .setAddress(Collections.singletonList(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev180222.interfaces._interface.ipv6.AddressBuilder()
+ .build()))
+ .build())
+ .build())
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceTypeTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceTypeTestUtils.java
new file mode 100644
index 000000000..c8e2e490e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceTypeTestUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.mockito.Mockito.doReturn;
+
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.Optional;
+import org.mockito.Matchers;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+final class InterfaceTypeTestUtils {
+
+ private InterfaceTypeTestUtils() {}
+
+ static void setupWriteContext(final WriteContext writeContext, final Class<? extends InterfaceType> ifcType) {
+ doReturn(new ModificationCache()).when(writeContext).getModificationCache();
+ doReturn(Optional.of(new InterfaceBuilder()
+ .setType(ifcType)
+ .build())).when(writeContext).readAfter(Matchers.any(InstanceIdentifier.class));
+ }
+
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizerTest.java
new file mode 100644
index 000000000..54267d02b
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedCustomizerTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 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.hc2vpp.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.InterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceUnnumberedCustomizerTest extends AbstractUnnumberedCustomizerTest {
+ private static final String UNNUMBERED_IFC_NAME = "eth2";
+ private static final int UNNUMBERED_IFC_ID = 2;
+ private static final InstanceIdentifier<Unnumbered> UNNUMBERED_IFC_IID = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(UNNUMBERED_IFC_NAME))
+ .augmentation(InterfaceUnnumberedAugmentation.class)
+ .child(Unnumbered.class);
+
+ @Override
+ protected int getUnnumberedIfcId() {
+ return UNNUMBERED_IFC_ID;
+ }
+
+ @Override
+ protected String getUnnumberedIfcName() {
+ return UNNUMBERED_IFC_NAME;
+ }
+
+ @Override
+ protected InstanceIdentifier<Unnumbered> getUnnumberedIfcIId() {
+ return UNNUMBERED_IFC_IID;
+ }
+
+ @Override
+ protected AbstractUnnumberedCustomizer getCustomizer() {
+ return new InterfaceUnnumberedCustomizer(api, new NamingContext("ifc-prefix", IFC_CTX_NAME));
+ }
+
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidatorTest.java
new file mode 100644
index 000000000..1d080e632
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceUnnumberedValidatorTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.InterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.UnnumberedBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceUnnumberedValidatorTest {
+
+ private InterfaceUnnumberedValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth2";
+ private static final String TARGET_IFC0_NAME = "eth0";
+ private static final InstanceIdentifier<Unnumbered> ID = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(InterfaceUnnumberedAugmentation.class)
+ .child(Unnumbered.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new InterfaceUnnumberedValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testWriteFailedNoUse() throws CreateValidationFailedException {
+ validator.validateWrite(ID, getUnnumberedIfc(null), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ validator.validateUpdate(ID, getUnnumberedIfc(TARGET_IFC0_NAME), getUnnumberedIfc(TARGET_IFC0_NAME),
+ writeContext);
+ }
+
+ @Test
+ public void testDeleteeSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+ }
+
+ private Unnumbered getUnnumberedIfc(String use) {
+ return new UnnumberedBuilder().setUse(use).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceValidatorTest.java
new file mode 100644
index 000000000..38e985844
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfaceValidatorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceValidatorTest {
+
+ private InterfaceValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth0";
+ private static final InstanceIdentifier<Interface> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME));
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new InterfaceValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, getInterface(true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoName() throws CreateValidationFailedException {
+ validator.validateWrite(ID, getInterface(null, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoEnableFlag() throws CreateValidationFailedException {
+ validator.validateWrite(ID, getInterface(null), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ validator.validateUpdate(ID, getInterface(true), getInterface(true), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, getInterface(true), writeContext);
+ }
+
+ private Interface getInterface(final String name, final Boolean enabled) {
+ return new InterfaceBuilder().setName(name).setEnabled(enabled).build();
+ }
+
+ private Interface getInterface(final Boolean enabled) {
+ return new InterfaceBuilder().setName(IF_NAME).setEnabled(enabled).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizerTest.java
new file mode 100644
index 000000000..0a2b8e428
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/InterfacesStatisticsCustomizerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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.hc2vpp.v3po.write;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.v3po.read.cache.InterfaceStatisticsManager;
+import io.fd.hc2vpp.v3po.read.cache.InterfaceStatisticsManagerImpl;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfacesStatsAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces.Statistics;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces.StatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesStatisticsCustomizerTest extends WriterCustomizerTest {
+
+ public static final InstanceIdentifier<Statistics> IID =
+ InstanceIdentifier.create(Interfaces.class).augmentation(VppInterfacesStatsAugmentation.class)
+ .child(Statistics.class);
+
+ private InterfacesStatisticsCustomizer customizer;
+ private InterfaceStatisticsManager statsManager;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ statsManager = new InterfaceStatisticsManagerImpl();
+ customizer = new InterfacesStatisticsCustomizer(statsManager);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ customizer.writeCurrentAttributes(IID, enableStats(true), writeContext);
+ Assert.assertTrue(statsManager.isStatisticsEnabled());
+ }
+
+ @Test
+ public void testUpdatetoEnabled() throws WriteFailedException {
+ customizer.updateCurrentAttributes(IID, enableStats(true), enableStats(false), writeContext);
+ Assert.assertFalse(statsManager.isStatisticsEnabled());
+ }
+
+ @Test
+ public void testUpdateToDisabled() throws WriteFailedException {
+ customizer.updateCurrentAttributes(IID, enableStats(false), enableStats(true), writeContext);
+ Assert.assertTrue(statsManager.isStatisticsEnabled());
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ customizer.deleteCurrentAttributes(IID, enableStats(true), writeContext);
+ Assert.assertFalse(statsManager.isStatisticsEnabled());
+ }
+
+ private Statistics enableStats(final boolean enabled) {
+ StatisticsBuilder builder = new StatisticsBuilder();
+ return builder.setEnabled(enabled).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/L2CustomizerTest.java
new file mode 100644
index 000000000..6b2c89824
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/L2CustomizerTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+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.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2Bridge;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2BridgeReply;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2Xconnect;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2XconnectReply;
+import io.fd.jvpp.core.types.L2PortType;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.Interconnection;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBased;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBased;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBasedBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+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<L2> 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 setUpTest() 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.portType = bvi ? L2PortType.L2_API_PORT_TYPE_BVI : L2PortType.L2_API_PORT_TYPE_NORMAL;
+ request.enable = booleanToByte(enable);
+ request.shg = 123;
+ return request;
+ }
+
+
+ private L2 l2(final Interconnection interconnection) {
+ return new L2Builder().setInterconnection(interconnection).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizerTest.java
new file mode 100644
index 000000000..3694dbebd
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/LoopbackCustomizerTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.jvpp.core.dto.CreateLoopback;
+import io.fd.jvpp.core.dto.CreateLoopbackReply;
+import io.fd.jvpp.core.dto.DeleteLoopback;
+import io.fd.jvpp.core.dto.DeleteLoopbackReply;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Loopback;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.LoopbackBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class LoopbackCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private LoopbackCustomizer loopCustomizer;
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.Loopback.class);
+ loopCustomizer = new LoopbackCustomizer(api, new NamingContext("ifcintest", IFC_TEST_INSTANCE));
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ doAnswer(new Answer() {
+
+ int idx = 0;
+
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ final CreateLoopbackReply t = new CreateLoopbackReply();
+ t.swIfIndex = idx++;
+ return future(t);
+ }
+ }).when(api).createLoopback(any(CreateLoopback.class));
+
+ loopCustomizer.writeCurrentAttributes(getLoopbackId("loop"), getLoopbackData("ff:ff:ff:ff:ff:ff"), writeContext);
+ loopCustomizer.writeCurrentAttributes(getLoopbackId("loop2"), getLoopbackData("ff:ff:ff:ff:ff:ff"), writeContext);
+
+ verify(api, times(2)).createLoopback(any(CreateLoopback.class));
+ verify(mappingContext).put(eq(mappingIid("loop", IFC_TEST_INSTANCE)), eq(
+ mapping("loop", 0).get()));
+ verify(mappingContext).put(eq(mappingIid("loop2", IFC_TEST_INSTANCE)), eq(
+ mapping("loop2", 1).get()));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final CreateLoopbackReply t = new CreateLoopbackReply();
+ t.swIfIndex = 0;
+ doReturn(future(t)).when(api).createLoopback(any(CreateLoopback.class));
+
+ doReturn(future(new DeleteLoopbackReply())).when(api).deleteLoopback(any(DeleteLoopback.class));
+
+ loopCustomizer.writeCurrentAttributes(getLoopbackId("loop"), getLoopbackData("ff:ff:ff:ff:ff:ff"), writeContext);
+ defineMapping(mappingContext, "loop", 1, IFC_TEST_INSTANCE);
+ loopCustomizer.deleteCurrentAttributes(getLoopbackId("loop"), getLoopbackData("ff:ff:ff:ff:ff:ff"), writeContext);
+
+ verify(api).createLoopback(any(CreateLoopback.class));
+ verify(api).deleteLoopback(any(DeleteLoopback.class));
+ verify(mappingContext).delete(eq(mappingIid("loop", IFC_TEST_INSTANCE)));
+ }
+
+ private InstanceIdentifier<Loopback> getLoopbackId(final String loop) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(loop)).augmentation(
+ VppInterfaceAugmentation.class).child(Loopback.class);
+ }
+
+ private Loopback getLoopbackData(final String mac) {
+ return new LoopbackBuilder().setMac(new PhysAddress(mac)).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/RewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/RewriteCustomizerTest.java
new file mode 100644
index 000000000..5202a19ee
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/RewriteCustomizerTest.java
@@ -0,0 +1,197 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.TagRewriteOperation;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.core.dto.L2InterfaceVlanTagRewrite;
+import io.fd.jvpp.core.dto.L2InterfaceVlanTagRewriteReply;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1q;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.Rewrite;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.RewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RewriteCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String IF_NAME = "local0";
+ private static final String VLAN_IF_NAME = "local0.1";
+ private static final int VLAN_IF_ID = 1;
+ private static final int VLAN_IF_INDEX = 11;
+ private NamingContext namingContext;
+ private RewriteCustomizer customizer;
+ private InstanceIdentifier<Rewrite> VLAN_IID;
+
+ private static InstanceIdentifier<Rewrite> getVlanTagRewriteId(final String name, final long index) {
+ final Class<ChildOf<? super SubInterface>> child = (Class) Rewrite.class;
+ final InstanceIdentifier id =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+ SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(index))
+ .child(child);
+ return id;
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ namingContext = new NamingContext("generatedSubInterfaceName", IFC_TEST_INSTANCE);
+ customizer = new RewriteCustomizer(api, namingContext);
+ VLAN_IID = getVlanTagRewriteId(IF_NAME, VLAN_IF_ID);
+ defineMapping(mappingContext, VLAN_IF_NAME, VLAN_IF_INDEX, IFC_TEST_INSTANCE);
+ }
+
+ private Rewrite generateRewrite(final TagRewriteOperation op) {
+ final RewriteBuilder builder = new RewriteBuilder();
+ builder.setPopTags((short) op.getPopTags());
+ builder.setVlanType(_802dot1q.class);
+ return builder.build();
+ }
+
+ private L2InterfaceVlanTagRewrite generateL2InterfaceVlanTagRewrite(final int swIfIndex,
+ final TagRewriteOperation op) {
+ final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite();
+ request.swIfIndex = swIfIndex;
+ request.vtrOp = op.ordinal();
+ request.pushDot1Q = 1;
+ return request;
+ }
+
+ /**
+ * Positive response
+ */
+ private void whenL2InterfaceVlanTagRewriteThenSuccess() {
+ doReturn(future(new L2InterfaceVlanTagRewriteReply())).when(api)
+ .l2InterfaceVlanTagRewrite(any(L2InterfaceVlanTagRewrite.class));
+ }
+
+ /**
+ * Failure response send
+ */
+ private void whenL2InterfaceVlanTagRewriteThenFailure() {
+ doReturn(failedFuture()).when(api).l2InterfaceVlanTagRewrite(any(L2InterfaceVlanTagRewrite.class));
+ }
+
+ private void verifyL2InterfaceVlanTagRewriteDeleteWasInvoked() throws VppInvocationException {
+ final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite();
+ request.swIfIndex = VLAN_IF_INDEX;
+ verify(api).l2InterfaceVlanTagRewrite(request);
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final TagRewriteOperation op = TagRewriteOperation.pop_2;
+ final Rewrite vlanTagRewrite = generateRewrite(op);
+
+ whenL2InterfaceVlanTagRewriteThenSuccess();
+
+ customizer.writeCurrentAttributes(VLAN_IID, vlanTagRewrite, writeContext);
+
+ verify(api).l2InterfaceVlanTagRewrite(generateL2InterfaceVlanTagRewrite(VLAN_IF_INDEX, op));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final TagRewriteOperation op = TagRewriteOperation.pop_2;
+ final Rewrite vlanTagRewrite = generateRewrite(op);
+
+ whenL2InterfaceVlanTagRewriteThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(VLAN_IID, vlanTagRewrite, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).l2InterfaceVlanTagRewrite(generateL2InterfaceVlanTagRewrite(VLAN_IF_INDEX, op));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ final Rewrite before = generateRewrite(TagRewriteOperation.pop_2);
+ final Rewrite after = generateRewrite(TagRewriteOperation.pop_1);
+
+ whenL2InterfaceVlanTagRewriteThenSuccess();
+
+ customizer.updateCurrentAttributes(VLAN_IID, before, after, writeContext);
+
+ verify(api)
+ .l2InterfaceVlanTagRewrite(generateL2InterfaceVlanTagRewrite(VLAN_IF_INDEX, TagRewriteOperation.pop_1));
+ }
+
+ @Test
+ public void testUpdateFailed() throws Exception {
+ final Rewrite before = generateRewrite(TagRewriteOperation.pop_2);
+ final Rewrite after = generateRewrite(TagRewriteOperation.pop_1);
+
+ whenL2InterfaceVlanTagRewriteThenFailure();
+
+ try {
+ customizer.updateCurrentAttributes(VLAN_IID, before, after, writeContext);
+ } catch (WriteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api)
+ .l2InterfaceVlanTagRewrite(
+ generateL2InterfaceVlanTagRewrite(VLAN_IF_INDEX, TagRewriteOperation.pop_1));
+ return;
+ }
+ fail("WriteFailedException.UpdateFailedException was expected");
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ whenL2InterfaceVlanTagRewriteThenSuccess();
+
+ customizer.deleteCurrentAttributes(VLAN_IID, null, writeContext);
+
+ verifyL2InterfaceVlanTagRewriteDeleteWasInvoked();
+ }
+
+ @Test
+ public void testDeleteFailed() throws Exception {
+ whenL2InterfaceVlanTagRewriteThenFailure();
+
+ try {
+ customizer.deleteCurrentAttributes(VLAN_IID, null, writeContext);
+ } catch (WriteFailedException e) {
+ Assert.assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyL2InterfaceVlanTagRewriteDeleteWasInvoked();
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizerTest.java
new file mode 100644
index 000000000..923db9b88
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceCustomizerTest.java
@@ -0,0 +1,256 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.core.dto.CreateSubif;
+import io.fd.jvpp.core.dto.CreateSubifReply;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlags;
+import io.fd.jvpp.core.dto.SwInterfaceSetFlagsReply;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1ad;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.vlan.tagged.VlanTaggedBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.Match;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.MatchBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.TagsBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.Tag;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.TagBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.TagKey;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag;
+import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTagBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private static final String SUPER_IF_NAME = "local0";
+ private static final int SUPER_IF_ID = 1;
+ private static final String SUB_IFACE_NAME = "local0.11";
+ private static final int SUBIF_INDEX = 11;
+ private static final short STAG_ID = 100;
+ private static final short CTAG_ID = 200;
+ private static final short CTAG_ANY_ID = 0; // only the *IdAny flag is set
+ private final Tag STAG_100;
+ private final Tag CTAG_200;
+ private final Tag CTAG_ANY;
+ private NamingContext namingContext;
+ private SubInterfaceCustomizer customizer;
+
+ public SubInterfaceCustomizerTest() {
+ STAG_100 = generateTag((short) 0, SVlan.class, new Dot1qTag.VlanId(new Dot1qVlanId((int) STAG_ID)));
+ CTAG_200 = generateTag((short) 1, CVlan.class, new Dot1qTag.VlanId(new Dot1qVlanId(200)));
+ CTAG_ANY = generateTag((short) 1, CVlan.class, new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any));
+ }
+
+ private static Tag generateTag(final short index, final Class<? extends Dot1qTagVlanType> tagType,
+ final Dot1qTag.VlanId vlanId) {
+ TagBuilder tag = new TagBuilder();
+ tag.setIndex(index);
+ tag.withKey(new TagKey(index));
+ final Dot1qTagBuilder dtag = new Dot1qTagBuilder();
+ dtag.setTagType(tagType);
+ dtag.setVlanId(vlanId);
+ tag.setDot1qTag(dtag.build());
+ return tag.build();
+ }
+
+ static Match generateMatch() {
+ final MatchBuilder match = new MatchBuilder();
+ final VlanTaggedBuilder tagged = new VlanTaggedBuilder();
+ tagged.setMatchExactTags(true);
+ match.setMatchType(
+ new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.VlanTaggedBuilder()
+ .setVlanTagged(tagged.build()).build());
+ return match.build();
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ namingContext = new NamingContext("generatedSubInterfaceName", IFC_TEST_INSTANCE);
+ customizer = new SubInterfaceCustomizer(api, namingContext);
+ defineMapping(mappingContext, SUB_IFACE_NAME, SUBIF_INDEX, IFC_TEST_INSTANCE);
+ defineMapping(mappingContext, SUPER_IF_NAME, SUPER_IF_ID, IFC_TEST_INSTANCE);
+ }
+
+ private SubInterface generateSubInterface(final boolean enabled, final List<Tag> tagList) {
+ SubInterfaceBuilder builder = new SubInterfaceBuilder();
+ builder.setVlanType(_802dot1ad.class);
+ builder.setIdentifier(11L);
+ final TagsBuilder tags = new TagsBuilder();
+
+ tags.setTag(tagList);
+
+ builder.setTags(tags.build());
+
+ builder.setMatch(generateMatch());
+ builder.setEnabled(enabled);
+ return builder.build();
+ }
+
+ private CreateSubif generateSubInterfaceRequest(final int superIfId, final short innerVlanId,
+ final boolean isInnerAny) {
+ CreateSubif request = new CreateSubif();
+ request.subId = 11;
+ request.swIfIndex = superIfId;
+ request.twoTags = 1;
+ request.innerVlanId = innerVlanId;
+ request.innerVlanIdAny = (byte) (isInnerAny
+ ? 1
+ : 0);
+ request.dot1Ad = 1;
+ request.outerVlanId = STAG_ID;
+ request.exactMatch = 1;
+ return request;
+ }
+
+ private SwInterfaceSetFlags generateSwInterfaceEnableRequest(final int swIfIndex) {
+ SwInterfaceSetFlags request = new SwInterfaceSetFlags();
+ request.swIfIndex = swIfIndex;
+ request.adminUpDown = 1;
+ return request;
+ }
+
+ private InstanceIdentifier<SubInterface> getSubInterfaceId(final String name, final long index) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
+ SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(index));
+ }
+
+ private void whenCreateSubifThenSuccess() {
+ doReturn(future(new CreateSubifReply())).when(api).createSubif(any(CreateSubif.class));
+ }
+
+ /**
+ * Failure response send
+ */
+ private void whenCreateSubifThenFailure() {
+ doReturn(failedFuture()).when(api).createSubif(any(CreateSubif.class));
+ }
+
+ private void whenSwInterfaceSetFlagsThenSuccess() {
+ doReturn(future(new SwInterfaceSetFlagsReply())).when(api).swInterfaceSetFlags(any(SwInterfaceSetFlags.class));
+ }
+
+ private SwInterfaceSetFlags verifySwInterfaceSetFlagsWasInvoked(final SwInterfaceSetFlags expected)
+ throws VppBaseCallException {
+ ArgumentCaptor<SwInterfaceSetFlags> argumentCaptor = ArgumentCaptor.forClass(SwInterfaceSetFlags.class);
+ verify(api).swInterfaceSetFlags(argumentCaptor.capture());
+ final SwInterfaceSetFlags actual = argumentCaptor.getValue();
+
+ assertEquals(expected.swIfIndex, actual.swIfIndex);
+ assertEquals(expected.adminUpDown, actual.adminUpDown);
+ return actual;
+ }
+
+ @Test
+ public void testCreateTwoTags() throws Exception {
+ final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
+ final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
+
+ whenCreateSubifThenSuccess();
+ whenSwInterfaceSetFlagsThenSuccess();
+
+ customizer.writeCurrentAttributes(id, subInterface, writeContext);
+
+ verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
+ verify(mappingContext)
+ .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
+ mapping(SUB_IFACE_NAME, 0).get()));
+ }
+
+ @Test
+ public void testCreateDot1qAnyTag() throws Exception {
+ final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_ANY));
+ final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
+
+ whenCreateSubifThenSuccess();
+ whenSwInterfaceSetFlagsThenSuccess();
+
+ customizer.writeCurrentAttributes(id, subInterface, writeContext);
+
+ verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ANY_ID, true));
+ verify(mappingContext)
+ .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
+ mapping(SUB_IFACE_NAME, 0).get()));
+ }
+
+ @Test
+ public void testCreateFailed() throws Exception {
+ final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
+ final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
+
+ whenCreateSubifThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, subInterface, writeContext);
+ } catch (WriteFailedException.CreateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
+ verify(mappingContext, times(0)).put(
+ eq(mappingIid(SUPER_IF_NAME, IFC_TEST_INSTANCE)),
+ eq(mapping(SUPER_IF_NAME, 0).get()));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ final List<Tag> tags = Arrays.asList(STAG_100, CTAG_200);
+ final SubInterface before = generateSubInterface(false, tags);
+ final SubInterface after = generateSubInterface(true, tags);
+ final InstanceIdentifier<SubInterface> id = getSubInterfaceId(SUPER_IF_NAME, SUBIF_INDEX);
+
+ whenSwInterfaceSetFlagsThenSuccess();
+ customizer.updateCurrentAttributes(id, before, after, writeContext);
+
+ verifySwInterfaceSetFlagsWasInvoked(generateSwInterfaceEnableRequest(SUBIF_INDEX));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testDelete() throws Exception {
+ final SubInterface subInterface = generateSubInterface(false, Arrays.asList(STAG_100, CTAG_200));
+ customizer.deleteCurrentAttributes(null, subInterface, writeContext);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2CustomizerTest.java
new file mode 100644
index 000000000..7812b813e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceL2CustomizerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2Bridge;
+import io.fd.jvpp.core.dto.SwInterfaceSetL2BridgeReply;
+import io.fd.jvpp.core.types.L2PortType;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBasedBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+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<L2> 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 setUpTest() 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.portType = bvi ? L2PortType.L2_API_PORT_TYPE_BVI : L2PortType.L2_API_PORT_TYPE_NORMAL;
+ request.enable = booleanToByte(enable);
+ request.shg = 123;
+ return request;
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizerTest.java
new file mode 100644
index 000000000..a80bbd750
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingCustomizerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.core.dto.SwInterfaceSetTable;
+import io.fd.jvpp.core.dto.SwInterfaceSetTableReply;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest implements ByteDataTranslator {
+
+ private static final String IFACE_CTX_NAME = "interface-ctx";
+ private static final String IF_NAME = "eth1";
+ private static final String SUBIF_NAME = "eth1.0";
+ private static final int IF_INDEX = 1;
+ private static final int SUBIF_INDEX = 0;
+ private static final InstanceIdentifier<Routing> VALID_ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceAugmentation.class)
+ .child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey((long) SUBIF_INDEX))
+ .child(Routing.class);
+ private static final int DISABLE_VRF = 0;
+
+ @Captor
+ private ArgumentCaptor<SwInterfaceSetTable> requestCaptor;
+
+
+ private SubInterfaceRoutingCustomizer customizer;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ customizer = new SubInterfaceRoutingCustomizer(api, new NamingContext("ifacePrefix", IFACE_CTX_NAME));
+ defineMapping(mappingContext, IF_NAME, IF_INDEX, IFACE_CTX_NAME);
+ defineMapping(mappingContext, SUBIF_NAME, SUBIF_INDEX, IFACE_CTX_NAME);
+ when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
+ when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
+ }
+
+ @Test
+ public void testWriteIpv4Vrf() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing v4Routing = new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
+ customizer.writeCurrentAttributes(VALID_ID, v4Routing, writeContext);
+ verifySetTableRequest(1, Collections.singleton(request(false, SUBIF_INDEX, 4)));
+ }
+
+ @Test
+ public void testWriteIpv6Vrf() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing v6Routing = new RoutingBuilder().setIpv6VrfId(new VniReference(3L)).build();
+ customizer.writeCurrentAttributes(VALID_ID, v6Routing, writeContext);
+ verifySetTableRequest(1, Collections.singleton(request(true, SUBIF_INDEX, 3)));
+ }
+
+ @Test
+ public void testUpdateIpv4Vrf() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing routingBefore = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
+ .setIpv4VrfId(new VniReference(4L)).build();
+ final Routing routingAfter = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
+ .setIpv4VrfId(new VniReference(5L)).build();
+ customizer.updateCurrentAttributes(VALID_ID, routingBefore, routingAfter, writeContext);
+ verifySetTableRequest(2, ImmutableSet.of(request(false, SUBIF_INDEX, 5),
+ request(true, SUBIF_INDEX, 3)));
+ }
+
+ @Test
+ public void testUpdateIpv6Vrf() throws WriteFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing routingBefore = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
+ .setIpv4VrfId(new VniReference(4L)).build();
+ final Routing routingAfter = new RoutingBuilder().setIpv6VrfId(new VniReference(8L))
+ .setIpv4VrfId(new VniReference(4L)).build();
+ customizer.updateCurrentAttributes(VALID_ID, routingBefore, routingAfter, writeContext);
+ verifySetTableRequest(2, ImmutableSet.of(request(false, SUBIF_INDEX, 4),
+ request(true, SUBIF_INDEX, 8)));
+ }
+
+ @Test
+ public void testDeleteIpv4Vrf() throws WriteFailedException {
+ when(writeContext.readAfter(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing v4Routing = new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
+ customizer.deleteCurrentAttributes(VALID_ID, v4Routing, writeContext);
+ verifySetTableRequest(1, Collections.singleton(request(false, SUBIF_INDEX, DISABLE_VRF)));
+ }
+
+
+ @Test
+ public void testDeleteIpv6Vrf() throws WriteFailedException {
+ when(writeContext.readAfter(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ final Routing v6Routing = new RoutingBuilder().setIpv6VrfId(new VniReference(3L)).build();
+ customizer.deleteCurrentAttributes(VALID_ID, v6Routing, writeContext);
+ verifySetTableRequest(1, Collections.singleton(request(true, SUBIF_INDEX, DISABLE_VRF)));
+ }
+
+ private SwInterfaceSetTable request(final boolean ipv6, final int index, final int vrf) {
+ final SwInterfaceSetTable request = new SwInterfaceSetTable();
+ request.vrfId = vrf;
+ request.swIfIndex = index;
+ request.isIpv6 = booleanToByte(ipv6);
+ return request;
+ }
+
+ private void verifySetTableRequest(final int times, final Set<SwInterfaceSetTable> requests) {
+ verify(api, times(times)).swInterfaceSetTable(requestCaptor.capture());
+ requestCaptor.getAllValues().containsAll(requests);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidatorTest.java
new file mode 100644
index 000000000..f24b5a607
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceRoutingValidatorTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingValidatorTest {
+
+ private SubInterfaceRoutingValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth1";
+ private static final int SUBIF_INDEX = 0;
+ private static final InstanceIdentifier<Routing> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(SubinterfaceAugmentation.class)
+ .child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey((long) SUBIF_INDEX))
+ .child(Routing.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new SubInterfaceRoutingValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateWrite(ID, getRouting(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedV4AddressPresent() throws CreateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v4AddressPresent()));
+ validator.validateWrite(ID, getRouting(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedV6AddressPresent() throws CreateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v6AddressPresent()));
+ validator.validateWrite(ID, getRouting(), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws UpdateValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateUpdate(ID, getRouting(), getRouting(), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+ validator.validateDelete(ID, getRouting(), writeContext);
+ }
+
+ private Routing getRouting() {
+ return new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
+ }
+
+ private SubInterface v4AddressPresent() {
+ return new SubInterfaceBuilder()
+ .setIpv4(new Ipv4Builder()
+ .setAddress(Collections.singletonList(new AddressBuilder().build()))
+ .build())
+ .build();
+ }
+
+ private SubInterface v6AddressPresent() {
+ return new SubInterfaceBuilder()
+ .setIpv6(new Ipv6Builder()
+ .setAddress(Collections.singletonList(
+ new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.ipv6.AddressBuilder()
+ .build()))
+ .build())
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizerTest.java
new file mode 100644
index 000000000..2be05ec00
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedCustomizerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 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.hc2vpp.v3po.write;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.SubinterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceUnnumberedCustomizerTest extends AbstractUnnumberedCustomizerTest {
+ private static final String PARENT_IFC_NAME = "eth2";
+ private static final String UNNUMBERED_IFC_NAME = "eth2.123";
+ private static final int UNNUMBERED_IFC_ID = 2;
+ private static final long UNNUMBERED_IFC_NUMBER = 123;
+ private static final InstanceIdentifier<Unnumbered> UNNUMBERED_IFC_IID = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(PARENT_IFC_NAME))
+ .augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(UNNUMBERED_IFC_NUMBER))
+ .augmentation(SubinterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
+
+ @Override
+ protected int getUnnumberedIfcId() {
+ return UNNUMBERED_IFC_ID;
+ }
+
+ @Override
+ protected String getUnnumberedIfcName() {
+ return UNNUMBERED_IFC_NAME;
+ }
+
+ @Override
+ protected InstanceIdentifier<Unnumbered> getUnnumberedIfcIId() {
+ return UNNUMBERED_IFC_IID;
+ }
+
+ @Override
+ protected AbstractUnnumberedCustomizer getCustomizer() {
+ return new SubInterfaceUnnumberedCustomizer(api, new NamingContext("ifc-prefix", IFC_CTX_NAME));
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidatorTest.java
new file mode 100644
index 000000000..a99f1b673
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceUnnumberedValidatorTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.InterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.UnnumberedBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceUnnumberedValidatorTest {
+
+ private SubInterfaceUnnumberedValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String IF_NAME = "eth2";
+ private static final String TARGET_IFC0_NAME = "eth0";
+ private static final InstanceIdentifier<Unnumbered> ID = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(IF_NAME))
+ .augmentation(InterfaceUnnumberedAugmentation.class)
+ .child(Unnumbered.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new SubInterfaceUnnumberedValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws DataValidationFailedException.CreateValidationFailedException {
+ validator.validateWrite(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testWriteFailedNoUse() throws DataValidationFailedException.CreateValidationFailedException {
+ validator.validateWrite(ID, getUnnumberedIfc(null), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws DataValidationFailedException.UpdateValidationFailedException {
+ validator.validateUpdate(ID, getUnnumberedIfc(TARGET_IFC0_NAME), getUnnumberedIfc(TARGET_IFC0_NAME),
+ writeContext);
+ }
+
+ @Test
+ public void testDeleteeSuccessful() throws DataValidationFailedException.DeleteValidationFailedException {
+ validator.validateDelete(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+ }
+
+ private Unnumbered getUnnumberedIfc(String use) {
+ return new UnnumberedBuilder().setUse(use).build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidatorTest.java
new file mode 100644
index 000000000..dce773b33
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/SubInterfaceValidatorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.Match;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceValidatorTest {
+
+ private SubInterfaceValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String SUPER_IF_NAME = "local0";
+ private static final String SUB_IFACE_NAME = "local0.11";
+ private static final long SUBIF_INDEX = 11;
+ private static final InstanceIdentifier<SubInterface> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(SUPER_IF_NAME))
+ .augmentation(
+ SubinterfaceAugmentation.class).child(SubInterfaces.class)
+ .child(SubInterface.class, new SubInterfaceKey(SUBIF_INDEX));
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new SubInterfaceValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator
+ .validateWrite(ID, generateSubInterface(11L, SubInterfaceCustomizerTest.generateMatch()), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoIdentifier() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateSubInterface(null, SubInterfaceCustomizerTest.generateMatch()),
+ writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoMatch() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateSubInterface(11L, null), writeContext);
+ }
+
+ private SubInterface generateSubInterface(final Long identifier, final Match match) {
+ return new SubInterfaceBuilder()
+ .setIdentifier(identifier)
+ .setMatch(match)
+ .setEnabled(true)
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/TapV2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/TapV2CustomizerTest.java
new file mode 100644
index 000000000..e7ba2fdce
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/TapV2CustomizerTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 Pantheon Technologies 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.hc2vpp.v3po.write;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.Ipv6Translator;
+import io.fd.hc2vpp.common.translate.util.MacTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.jvpp.core.dto.TapCreateV2;
+import io.fd.jvpp.core.dto.TapCreateV2Reply;
+import io.fd.jvpp.core.dto.TapDeleteV2;
+import io.fd.jvpp.core.dto.TapDeleteV2Reply;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2Builder;
+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.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TapV2CustomizerTest extends WriterCustomizerTest
+ implements Ipv4Translator, Ipv6Translator, MacTranslator {
+
+ private static final String IFC_TEST_INSTANCE = "ifc-test-instance";
+ private TapV2Customizer tapCustomizer;
+ private static final String HOST_IF_NAME = "tapV21";
+ private static final String HOST_BRIDGE = "TestBridge";
+ private static final String HOST_IPV4_PREFIX = "192.168.255.100";
+ private static final byte HOST_IPV4_PREFIX_LEN = 24;
+ private static final String HOST_IPV4_GW = "192.168.255.1";
+ private static final String HOST_IPV6_PREFIX = "a::100";
+ private static final String HOST_IPV6_GW = "a::1";
+ private static final byte HOST_IPV6_PREFIX_LEN = -128;
+ private static final int HOST_IPV6_PREFIX_LEN_EXP = 128;
+ private static final int RX_TX_RING_SIZE = 512;
+ private static final String HOST_MAC = "00:ee:ee:ee:ee:ee";
+ private static final String HOST_NAMESPACE = "testHostNS";
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.TapV2.class);
+ tapCustomizer = new TapV2Customizer(api, new NamingContext("ifcintest", IFC_TEST_INSTANCE));
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final AtomicInteger idx = new AtomicInteger(0);
+ doAnswer((i) -> {
+ final TapCreateV2 tapData = i.getArgument(0);
+ if (tapData == null) {
+ return failedFuture();
+ }
+
+ Assert.assertArrayEquals(tapData.hostBridge, HOST_BRIDGE.getBytes());
+ Assert.assertEquals(tapData.hostBridgeSet, 1);
+ Assert.assertArrayEquals(tapData.hostIfName, HOST_IF_NAME.getBytes());
+ Assert.assertEquals(tapData.hostIfNameSet, 1);
+ Assert.assertArrayEquals(tapData.hostNamespace, HOST_NAMESPACE.getBytes());
+ Assert.assertEquals(tapData.hostNamespaceSet, 1);
+ Assert.assertArrayEquals(tapData.hostIp4Addr, ipv4AddressPrefixToArray(
+ new Ipv4Prefix(String.format("%s/%d", HOST_IPV4_PREFIX, HOST_IPV4_PREFIX_LEN))));
+ Assert.assertEquals(tapData.hostIp4AddrSet, 1);
+ Assert.assertEquals(tapData.hostIp4PrefixLen, HOST_IPV4_PREFIX_LEN);
+ Assert.assertArrayEquals(tapData.hostIp6Addr, ipv6AddressPrefixToArray(
+ new Ipv6Prefix(String.format("%s/%d", HOST_IPV6_PREFIX, HOST_IPV6_PREFIX_LEN_EXP))));
+ Assert.assertEquals(tapData.hostIp6AddrSet, 1);
+ Assert.assertEquals(tapData.hostIp6PrefixLen, HOST_IPV6_PREFIX_LEN);
+ Assert.assertArrayEquals(tapData.hostIp4Gw, ipv4AddressPrefixToArray(
+ new Ipv4Prefix(String.format("%s/%d", HOST_IPV4_GW, 24))));
+ Assert.assertEquals(tapData.hostIp4GwSet, 1);
+ Assert.assertArrayEquals(tapData.hostIp6Gw, ipv6AddressPrefixToArray(
+ new Ipv6Prefix(String.format("%s/%d", HOST_IPV6_GW, 96))));
+ Assert.assertEquals(tapData.hostIp6GwSet, 1);
+ Assert.assertArrayEquals(tapData.hostMacAddr, parseMac(HOST_MAC));
+ Assert.assertEquals(tapData.hostMacAddrSet, 1);
+ Assert.assertEquals(tapData.rxRingSz, RX_TX_RING_SIZE);
+ Assert.assertEquals(tapData.txRingSz, RX_TX_RING_SIZE);
+ final TapCreateV2Reply t = new TapCreateV2Reply();
+ t.swIfIndex = idx.getAndIncrement();
+ return future(t);
+
+ }).when(api).tapCreateV2(any(TapCreateV2.class));
+
+ tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap"), writeContext);
+ tapCustomizer.writeCurrentAttributes(getTapId("tap2"), getTapData("tap2"), writeContext);
+
+ verify(api, times(2)).tapCreateV2(any(TapCreateV2.class));
+ verify(mappingContext).put(eq(mappingIid("tap", IFC_TEST_INSTANCE)), eq(
+ mapping("tap", 0).get()));
+ verify(mappingContext).put(eq(mappingIid("tap2", IFC_TEST_INSTANCE)), eq(
+ mapping("tap2", 1).get()));
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ final TapCreateV2Reply t = new TapCreateV2Reply();
+ t.swIfIndex = 0;
+ doReturn(future(t)).when(api).tapCreateV2(any(TapCreateV2.class));
+
+ doReturn(future(new TapDeleteV2Reply())).when(api).tapDeleteV2(any(TapDeleteV2.class));
+ tapCustomizer.writeCurrentAttributes(getTapId("tap-v2"), getTapData("tap-v2"), writeContext);
+ defineMapping(mappingContext, "tap-v2", 1, IFC_TEST_INSTANCE);
+ tapCustomizer.deleteCurrentAttributes(getTapId("tap-v2"), getTapData("tap-v2"), writeContext);
+
+ verify(api).tapCreateV2(any(TapCreateV2.class));
+ verify(api).tapDeleteV2(any(TapDeleteV2.class));
+ verify(mappingContext).delete(eq(mappingIid("tap-v2", IFC_TEST_INSTANCE)));
+ }
+
+ private InstanceIdentifier<TapV2> getTapId(final String tap) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(tap)).augmentation(
+ VppInterfaceAugmentation.class).child(TapV2.class);
+ }
+
+ private TapV2 getTapData(final String tap) {
+ return new TapV2Builder()
+ .setHostInterfaceName(HOST_IF_NAME)
+ .setMac(new PhysAddress(HOST_MAC))
+ .setTag(tap + "_tag")
+ .setHostBridge(HOST_BRIDGE)
+ .setHostIpv4Address(new Ipv4Prefix(String.format("%s/%s", HOST_IPV4_PREFIX, HOST_IPV4_PREFIX_LEN)))
+ .setHostIpv4Gateway(new Ipv4Address(HOST_IPV4_GW))
+ .setHostIpv6Address(new Ipv6Prefix(String.format("%s/%s", HOST_IPV6_PREFIX, HOST_IPV6_PREFIX_LEN_EXP)))
+ .setHostIpv6Gateway(new Ipv6Address(HOST_IPV6_GW))
+ .setRxRingSize(RX_TX_RING_SIZE)
+ .setTxRingSize(RX_TX_RING_SIZE)
+ .setHostMac(new PhysAddress(HOST_MAC))
+ .setHostNamespace(HOST_NAMESPACE)
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizerTest.java
new file mode 100644
index 000000000..0b4d1bce9
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserCustomizerTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.Ipv4Translator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.core.dto.CreateVhostUserIf;
+import io.fd.jvpp.core.dto.CreateVhostUserIfReply;
+import io.fd.jvpp.core.dto.DeleteVhostUserIf;
+import io.fd.jvpp.core.dto.DeleteVhostUserIfReply;
+import io.fd.jvpp.core.dto.ModifyVhostUserIf;
+import io.fd.jvpp.core.dto.ModifyVhostUserIfReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUserRole;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUserBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VhostUserCustomizerTest extends WriterCustomizerTest implements Ipv4Translator {
+
+ private static final int IFACE_ID = 1;
+ private static final String IFACE_NAME = "eth0";
+ private static final InstanceIdentifier<VhostUser> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(VhostUser.class);
+ private VhostUserCustomizer customizer;
+
+ static VhostUser generateVhostUser(final VhostUserRole role, final String socketName) {
+ VhostUserBuilder builder = new VhostUserBuilder();
+ builder.setRole(role);
+ builder.setSocket(socketName);
+ return builder.build();
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUser.class);
+ customizer = new VhostUserCustomizer(api, new NamingContext("generatedInterfaceName", "test-instance"));
+ }
+
+ private CreateVhostUserIf verifyCreateVhostUserIfWasInvoked(final VhostUser vhostUser)
+ throws VppInvocationException {
+ ArgumentCaptor<CreateVhostUserIf> argumentCaptor = ArgumentCaptor.forClass(CreateVhostUserIf.class);
+ verify(api).createVhostUserIf(argumentCaptor.capture());
+ final CreateVhostUserIf actual = argumentCaptor.getValue();
+ assertEquals(0, actual.customDevInstance);
+
+ assertEquals(booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole())), actual.isServer);
+ assertEquals(0, actual.renumber);
+ assertEquals(0, actual.useCustomMac);
+ assertArrayEquals(vhostUser.getSocket().getBytes(), actual.sockFilename);
+ assertNotNull(actual.macAddress);
+ return actual;
+ }
+
+ private ModifyVhostUserIf verifyModifyVhostUserIfWasInvoked(final VhostUser vhostUser, final int swIfIndex)
+ throws VppInvocationException {
+ ArgumentCaptor<ModifyVhostUserIf> argumentCaptor = ArgumentCaptor.forClass(ModifyVhostUserIf.class);
+ verify(api).modifyVhostUserIf(argumentCaptor.capture());
+ final ModifyVhostUserIf actual = argumentCaptor.getValue();
+ assertEquals(0, actual.customDevInstance);
+
+ assertEquals(booleanToByte(VhostUserRole.Server.equals(vhostUser.getRole())), actual.isServer);
+ assertEquals(0, actual.renumber);
+ assertEquals(swIfIndex, actual.swIfIndex);
+ assertArrayEquals(vhostUser.getSocket().getBytes(), actual.sockFilename);
+ return actual;
+ }
+
+ private DeleteVhostUserIf verifyDeleteVhostUserIfWasInvoked(final int swIfIndex) throws VppInvocationException {
+ ArgumentCaptor<DeleteVhostUserIf> argumentCaptor = ArgumentCaptor.forClass(DeleteVhostUserIf.class);
+ verify(api).deleteVhostUserIf(argumentCaptor.capture());
+ final DeleteVhostUserIf actual = argumentCaptor.getValue();
+ assertEquals(swIfIndex, actual.swIfIndex);
+ return actual;
+ }
+
+ @Test
+ public void testWriteCurrentAttributes() throws Exception {
+ final VhostUser vhostUser = generateVhostUser(VhostUserRole.Server, "socketName");
+
+ when(api.createVhostUserIf(any(CreateVhostUserIf.class))).thenReturn(future(new CreateVhostUserIfReply()));
+
+ customizer.writeCurrentAttributes(ID, vhostUser, writeContext);
+ verifyCreateVhostUserIfWasInvoked(vhostUser);
+ verify(mappingContext).put(eq(mappingIid(IFACE_NAME, "test-instance")), eq(
+ mapping(IFACE_NAME, 0).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesFailed() throws Exception {
+ final VhostUser vhostUser = generateVhostUser(VhostUserRole.Client, "socketName");
+
+ doReturn(failedFuture()).when(api).createVhostUserIf(any(CreateVhostUserIf.class));
+
+ try {
+ customizer.writeCurrentAttributes(ID, vhostUser, writeContext);
+ } catch (WriteFailedException.CreateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyCreateVhostUserIfWasInvoked(vhostUser);
+ verifyZeroInteractions(mappingContext);
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test
+ public void testUpdateCurrentAttributes() throws Exception {
+ final VhostUser vhostUserBefore = generateVhostUser(VhostUserRole.Client, "socketName0");
+ final VhostUser vhostUserAfter = generateVhostUser(VhostUserRole.Server, "socketName1");
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, "test-instance");
+
+ when(api.modifyVhostUserIf(any(ModifyVhostUserIf.class))).thenReturn(future(new ModifyVhostUserIfReply()));
+
+ customizer.updateCurrentAttributes(ID, vhostUserBefore, vhostUserAfter, writeContext);
+ verifyModifyVhostUserIfWasInvoked(vhostUserAfter, IFACE_ID);
+ }
+
+ @Test
+ public void testUpdateCurrentAttributesFailed() throws Exception {
+ final VhostUser vhostUserBefore = generateVhostUser(VhostUserRole.Client, "socketName0");
+ final VhostUser vhostUserAfter = generateVhostUser(VhostUserRole.Server, "socketName1");
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, "test-instance");
+
+ doReturn(failedFuture()).when(api).modifyVhostUserIf(any(ModifyVhostUserIf.class));
+
+ try {
+ customizer.updateCurrentAttributes(ID, vhostUserBefore, vhostUserAfter, writeContext);
+ } catch (WriteFailedException.UpdateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyModifyVhostUserIfWasInvoked(vhostUserAfter, IFACE_ID);
+ return;
+ }
+ fail("WriteFailedException.UpdateFailedException was expected");
+ }
+
+ @Test
+ public void testDeleteCurrentAttributes() throws Exception {
+ final VhostUser vhostUser = generateVhostUser(VhostUserRole.Client, "socketName");
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, "test-instance");
+
+ when(api.deleteVhostUserIf(any(DeleteVhostUserIf.class))).thenReturn(future(new DeleteVhostUserIfReply()));
+
+ customizer.deleteCurrentAttributes(ID, vhostUser, writeContext);
+ verifyDeleteVhostUserIfWasInvoked(IFACE_ID);
+ verify(mappingContext).delete(eq(mappingIid(IFACE_NAME, "test-instance")));
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesFailed() throws Exception {
+ final VhostUser vhostUser = generateVhostUser(VhostUserRole.Client, "socketName");
+ defineMapping(mappingContext, IFACE_NAME, IFACE_ID, "test-instance");
+
+ doReturn(failedFuture()).when(api).deleteVhostUserIf(any(DeleteVhostUserIf.class));
+
+ try {
+ customizer.deleteCurrentAttributes(ID, vhostUser, writeContext);
+ } catch (WriteFailedException.DeleteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyDeleteVhostUserIfWasInvoked(IFACE_ID);
+ // Delete from context not invoked if delete from VPP failed
+ verify(mappingContext, times(0)).delete(eq(mappingIid(IFACE_NAME, "test-instance")));
+ verify(mappingContext).read(eq(mappingIid(IFACE_NAME, "test-instance")));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserValidatorTest.java
new file mode 100644
index 000000000..a5a89a214
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VhostUserValidatorTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUserRole;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VhostUserValidatorTest {
+
+ private VhostUserValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+
+ private static final String SOCKET = "testSocket";
+ private static final String IFACE_NAME = "eth0";
+ private static final InstanceIdentifier<VhostUser> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(VhostUser.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new VhostUserValidator(ifcContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws DataValidationFailedException.CreateValidationFailedException {
+ validator.validateWrite(ID, getVhostUser(SOCKET), writeContext);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testWriteFailedNoSocket() throws DataValidationFailedException.CreateValidationFailedException {
+ validator.validateWrite(ID, getVhostUser(null), writeContext);
+ }
+
+ @Test
+ public void testUpdateSuccessful() throws DataValidationFailedException.UpdateValidationFailedException {
+ validator.validateUpdate(ID, getVhostUser(SOCKET),
+ getVhostUser(SOCKET), writeContext);
+ }
+
+ @Test
+ public void testDeleteeSuccessful() throws DataValidationFailedException.DeleteValidationFailedException {
+ validator.validateDelete(ID, getVhostUser(SOCKET), writeContext);
+ }
+
+ private VhostUser getVhostUser(final String socketName) {
+ return VhostUserCustomizerTest.generateVhostUser(VhostUserRole.Client, socketName);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanCustomizerTest.java
new file mode 100644
index 000000000..44c8a2ee7
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanCustomizerTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.VppInvocationException;
+import io.fd.jvpp.core.dto.VxlanAddDelTunnel;
+import io.fd.jvpp.core.dto.VxlanAddDelTunnelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.L2Input;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanCustomizerTest extends WriterCustomizerTest implements AddressTranslator {
+
+ private static final byte ADD_VXLAN = 1;
+ private static final byte DEL_VXLAN = 0;
+
+ @Mock
+ private DisabledInterfacesManager disableContext;
+
+ private VxlanCustomizer customizer;
+ private String ifaceName;
+ private InstanceIdentifier<Vxlan> id;
+
+ private static Vxlan generateVxlan(long vni) {
+ final VxlanBuilder builder = new VxlanBuilder();
+ builder.setSrc(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.10")));
+ builder.setDst(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.11")));
+ builder.setEncapVrfId(new VniReference(123L));
+ builder.setVni(new VxlanVni(Long.valueOf(vni)));
+ builder.setDecapNext(L2Input.class);
+ return builder.build();
+ }
+
+ private static Vxlan generateVxlan() {
+ return generateVxlan(Long.valueOf(11));
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanTunnel.class);
+
+ customizer =
+ new VxlanCustomizer(api, new NamingContext("generateInterfaceNAme", "test-instance"), disableContext);
+
+ ifaceName = "eth0";
+ id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
+ .augmentation(VppInterfaceAugmentation.class).child(Vxlan.class);
+ }
+
+ private void whenVxlanAddDelTunnelThenSuccess() {
+ when(api.vxlanAddDelTunnel(any(VxlanAddDelTunnel.class))).thenReturn(future(new VxlanAddDelTunnelReply()));
+ }
+
+ private void whenVxlanAddDelTunnelThenFailure() {
+ doReturn(failedFuture()).when(api).vxlanAddDelTunnel(any(VxlanAddDelTunnel.class));
+ }
+
+ private VxlanAddDelTunnel verifyVxlanAddDelTunnelWasInvoked(final Vxlan vxlan) throws VppInvocationException {
+ ArgumentCaptor<VxlanAddDelTunnel> argumentCaptor = ArgumentCaptor.forClass(VxlanAddDelTunnel.class);
+ verify(api).vxlanAddDelTunnel(argumentCaptor.capture());
+ final VxlanAddDelTunnel actual = argumentCaptor.getValue();
+ assertEquals(0, actual.isIpv6);
+ assertEquals(1, actual.decapNextIndex);
+
+ assertArrayEquals(ipAddressToArray(vxlan.getSrc()), actual.srcAddress);
+ assertArrayEquals(ipAddressToArray(vxlan.getDst()), actual.dstAddress);
+ assertEquals(vxlan.getEncapVrfId().getValue().intValue(), actual.encapVrfId);
+ assertEquals(vxlan.getVni().getValue().intValue(), actual.vni);
+ return actual;
+ }
+
+ private void verifyVxlanAddWasInvoked(final Vxlan vxlan) throws VppInvocationException {
+ final VxlanAddDelTunnel actual = verifyVxlanAddDelTunnelWasInvoked(vxlan);
+ assertEquals(ADD_VXLAN, actual.isAdd);
+ }
+
+ private void verifyVxlanDeleteWasInvoked(final Vxlan vxlan) throws VppInvocationException {
+ final VxlanAddDelTunnel actual = verifyVxlanAddDelTunnelWasInvoked(vxlan);
+ assertEquals(DEL_VXLAN, actual.isAdd);
+ }
+
+ @Test
+ public void testWriteCurrentAttributes() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenSuccess();
+ noMappingDefined(mappingContext, ifaceName, "test-instance");
+
+ customizer.writeCurrentAttributes(id, vxlan, writeContext);
+ verifyVxlanAddWasInvoked(vxlan);
+ verify(mappingContext).put(eq(mappingIid(ifaceName, "test-instance")), eq(mapping(ifaceName, 0).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesWithExistingVxlanPlaceholder() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenSuccess();
+ noMappingDefined(mappingContext, ifaceName, "test-instance");
+ doReturn(true).when(disableContext).isInterfaceDisabled(0, mappingContext);
+
+ customizer.writeCurrentAttributes(id, vxlan, writeContext);
+ verifyVxlanAddWasInvoked(vxlan);
+ verify(mappingContext).put(eq(mappingIid(ifaceName, "test-instance")), eq(mapping(ifaceName, 0).get()));
+ verify(disableContext).removeDisabledInterface(0, mappingContext);
+ }
+
+ @Test
+ public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+ final int ifaceId = 0;
+
+ whenVxlanAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, ifaceName, ifaceId, "test-instance");
+
+ customizer.writeCurrentAttributes(id, vxlan, writeContext);
+ verifyVxlanAddWasInvoked(vxlan);
+
+ // Remove the first mapping before putting in the new one
+ verify(mappingContext).delete(eq(mappingIid(ifaceName, "test-instance")));
+ verify(mappingContext)
+ .put(eq(mappingIid(ifaceName, "test-instance")), eq(mapping(ifaceName, ifaceId).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesFailed() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, vxlan, writeContext);
+ } catch (WriteFailedException.CreateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyVxlanAddWasInvoked(vxlan);
+ // Mapping not stored due to failure
+ verify(mappingContext, times(0))
+ .put(eq(mappingIid(ifaceName, "test-instance")), eq(mapping(ifaceName, 0).get()));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdateCurrentAttributes() throws Exception {
+ customizer.updateCurrentAttributes(id, generateVxlan(10), generateVxlan(11), writeContext);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributes() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, ifaceName, 1, "test-instance");
+
+ customizer.deleteCurrentAttributes(id, vxlan, writeContext);
+ verifyVxlanDeleteWasInvoked(vxlan);
+ verify(mappingContext).delete(eq(mappingIid(ifaceName, "test-instance")));
+ verify(disableContext).disableInterface(1, mappingContext);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesaFailed() throws Exception {
+ final Vxlan vxlan = generateVxlan();
+
+ whenVxlanAddDelTunnelThenFailure();
+ defineMapping(mappingContext, ifaceName, 1, "test-instance");
+
+ try {
+ customizer.deleteCurrentAttributes(id, vxlan, writeContext);
+ } catch (WriteFailedException.DeleteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyVxlanDeleteWasInvoked(vxlan);
+ verify(mappingContext, times(0)).delete(eq(mappingIid(ifaceName, "test-instance")));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizerTest.java
new file mode 100644
index 000000000..9d1581551
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeCustomizerTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.hc2vpp.v3po.write;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppBaseCallException;
+import io.fd.jvpp.core.dto.VxlanGpeAddDelTunnel;
+import io.fd.jvpp.core.dto.VxlanGpeAddDelTunnelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeNextProtocol;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanGpeCustomizerTest extends WriterCustomizerTest implements AddressTranslator {
+
+ private static final byte ADD_VXLAN_GPE = 1;
+ private static final byte DEL_VXLAN_GPE = 0;
+
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
+
+ private VxlanGpeCustomizer customizer;
+ private String ifaceName;
+ private InstanceIdentifier<VxlanGpe> id;
+
+ private static VxlanGpe generateVxlanGpe(long vni) {
+ final VxlanGpeBuilder builder = new VxlanGpeBuilder();
+ builder.setLocal(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.10")));
+ builder.setRemote(new IpAddressNoZone(new Ipv4AddressNoZone("192.168.20.11")));
+ builder.setVni(new VxlanGpeVni(Long.valueOf(vni)));
+ builder.setNextProtocol(VxlanGpeNextProtocol.forValue(1));
+ builder.setEncapVrfId(Long.valueOf(123));
+ builder.setDecapVrfId(Long.valueOf(456));
+ return builder.build();
+ }
+
+ private static VxlanGpe generateVxlanGpe() {
+ return generateVxlanGpe(Long.valueOf(11));
+ }
+
+ @Override
+ public void setUpTest() throws Exception {
+ InterfaceTypeTestUtils.setupWriteContext(writeContext,
+ org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeTunnel.class);
+ NamingContext namingContext = new NamingContext("generateInterfaceName", "test-instance");
+ customizer = new VxlanGpeCustomizer(api, namingContext, interfaceDisableContext);
+
+ ifaceName = "elth0";
+ id = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(ifaceName))
+ .augmentation(VppInterfaceAugmentation.class).child(VxlanGpe.class);
+ }
+
+ private void whenVxlanGpeAddDelTunnelThenSuccess() {
+ when(api.vxlanGpeAddDelTunnel(any(VxlanGpeAddDelTunnel.class)))
+ .thenReturn(future(new VxlanGpeAddDelTunnelReply()));
+ }
+
+ private void whenVxlanGpeAddDelTunnelThenFailure() {
+ doReturn(failedFuture()).when(api).vxlanGpeAddDelTunnel(any(VxlanGpeAddDelTunnel.class));
+ }
+
+ private VxlanGpeAddDelTunnel verifyVxlanGpeAddDelTunnelWasInvoked(final VxlanGpe vxlanGpe)
+ throws VppBaseCallException {
+ ArgumentCaptor<VxlanGpeAddDelTunnel> argumentCaptor = ArgumentCaptor.forClass(VxlanGpeAddDelTunnel.class);
+ verify(api).vxlanGpeAddDelTunnel(argumentCaptor.capture());
+ final VxlanGpeAddDelTunnel actual = argumentCaptor.getValue();
+ assertEquals(0, actual.isIpv6);
+ assertArrayEquals(ipAddressToArray(vxlanGpe.getLocal()), actual.local);
+ assertArrayEquals(ipAddressToArray(vxlanGpe.getRemote()), actual.remote);
+ assertEquals(vxlanGpe.getVni().getValue().intValue(), actual.vni);
+ assertEquals(vxlanGpe.getNextProtocol().getIntValue(), actual.protocol);
+ assertEquals(vxlanGpe.getEncapVrfId().intValue(), actual.encapVrfId);
+ assertEquals(vxlanGpe.getDecapVrfId().intValue(), actual.decapVrfId);
+ return actual;
+ }
+
+ private void verifyVxlanGpeAddWasInvoked(final VxlanGpe vxlanGpe) throws VppBaseCallException {
+ final VxlanGpeAddDelTunnel actual = verifyVxlanGpeAddDelTunnelWasInvoked(vxlanGpe);
+ assertEquals(ADD_VXLAN_GPE, actual.isAdd);
+ }
+
+ private void verifyVxlanGpeDeleteWasInvoked(final VxlanGpe vxlanGpe) throws VppBaseCallException {
+ final VxlanGpeAddDelTunnel actual = verifyVxlanGpeAddDelTunnelWasInvoked(vxlanGpe);
+ assertEquals(DEL_VXLAN_GPE, actual.isAdd);
+ }
+
+ @Test
+ public void testWriteCurrentAttributes() throws Exception {
+ final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+ whenVxlanGpeAddDelTunnelThenSuccess();
+ noMappingDefined(mappingContext, ifaceName, "test-instance");
+
+ customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+ verifyVxlanGpeAddWasInvoked(vxlanGpe);
+ verify(mappingContext).put(eq(mappingIid(ifaceName, "test-instance")), eq(
+ mapping(ifaceName, 0).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesMappingAlreadyPresent() throws Exception {
+ final VxlanGpe vxlanGpe = generateVxlanGpe();
+ final int ifaceId = 0;
+
+ whenVxlanGpeAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, ifaceName, ifaceId, "test-instance");
+
+ customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+ verifyVxlanGpeAddWasInvoked(vxlanGpe);
+
+ // Remove the first mapping before putting in the new one
+ verify(mappingContext).delete(eq(mappingIid(ifaceName, "test-instance")));
+ verify(mappingContext).put(eq(mappingIid(ifaceName, "test-instance")),
+ eq(mapping(ifaceName, ifaceId).get()));
+ }
+
+ @Test
+ public void testWriteCurrentAttributesFailed() throws Exception {
+ final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+ whenVxlanGpeAddDelTunnelThenFailure();
+
+ try {
+ customizer.writeCurrentAttributes(id, vxlanGpe, writeContext);
+ } catch (WriteFailedException.CreateFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyVxlanGpeAddWasInvoked(vxlanGpe);
+ // Mapping not stored due to failure
+ verify(mappingContext, times(0))
+ .put(eq(mappingIid(ifaceName, "test-instance")), eq(
+ mapping(ifaceName, 0).get()));
+ return;
+ }
+ fail("WriteFailedException.CreateFailedException was expected");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testUpdateCurrentAttributes() throws Exception {
+ customizer.updateCurrentAttributes(id, generateVxlanGpe(10), generateVxlanGpe(11), writeContext);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributes() throws Exception {
+ final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+ whenVxlanGpeAddDelTunnelThenSuccess();
+ defineMapping(mappingContext, ifaceName, 1, "test-instance");
+
+ customizer.deleteCurrentAttributes(id, vxlanGpe, writeContext);
+ verifyVxlanGpeDeleteWasInvoked(vxlanGpe);
+ verify(mappingContext).delete(eq(mappingIid(ifaceName, "test-instance")));
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesaFailed() throws Exception {
+ final VxlanGpe vxlanGpe = generateVxlanGpe();
+
+ whenVxlanGpeAddDelTunnelThenFailure();
+ defineMapping(mappingContext, ifaceName, 1, "test-instance");
+
+ try {
+ customizer.deleteCurrentAttributes(id, vxlanGpe, writeContext);
+ } catch (WriteFailedException.DeleteFailedException e) {
+ assertTrue(e.getCause() instanceof VppBaseCallException);
+ verifyVxlanGpeDeleteWasInvoked(vxlanGpe);
+ verify(mappingContext, times(0)).delete(eq(mappingIid(ifaceName, "test-instance")));
+ return;
+ }
+ fail("WriteFailedException.DeleteFailedException was expected");
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidatorTest.java
new file mode 100644
index 000000000..aad110388
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanGpeValidatorTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeNextProtocol;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanGpeValidatorTest {
+
+ private VxlanGpeValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
+
+ private static final String IPV6 = "a::100";
+ private static final String IPV4_1 = "192.168.20.10";
+ private static final String IPV4_2 = "192.168.20.11";
+ private static final Long VNI = Long.valueOf(11);
+ private static final Long ENCAP = Long.valueOf(123);
+ private static final Long DECAP = Long.valueOf(321);
+ private static final String IFACE_NAME = "eth0";
+ private static final InstanceIdentifier<VxlanGpe> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(VxlanGpe.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new VxlanGpeValidator(ifcContext, interfaceDisableContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanCorrect(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedMixedIpFamilies() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanMixedIpFamilies(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoLocal() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(false, true, true, true, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoRemote() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, false, true, true, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoEncapVrfId() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, false, true, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoDecapVrfId() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, true, false, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoVNI() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, true, true, false, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoNextProtocol() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, true, true, true, false), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, generateVxlanCorrect(), writeContext);
+ }
+
+ private VxlanGpe generateVxlanSetFields(final boolean src, final boolean dst, final boolean encapVrfId,
+ final boolean decapVrfId, final boolean vni, final boolean protocol) {
+ final VxlanGpeBuilder builder = new VxlanGpeBuilder();
+ builder.setLocal(src
+ ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1))
+ : null);
+ builder.setRemote(dst
+ ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2))
+ : null);
+ builder.setEncapVrfId(encapVrfId
+ ? ENCAP
+ : null);
+ builder.setDecapVrfId(decapVrfId
+ ? DECAP
+ : null);
+ builder.setVni(vni
+ ? new VxlanGpeVni(VNI)
+ : null);
+ builder.setNextProtocol(protocol
+ ? VxlanGpeNextProtocol.forValue(1)
+ : null);
+ return builder.build();
+ }
+
+ private VxlanGpe generateVxlanCorrect() {
+ return generateVxlanSetFields(true, true, true, true, true, true);
+ }
+
+ private VxlanGpe generateVxlanMixedIpFamilies() {
+ return new VxlanGpeBuilder()
+ .setLocal(new IpAddressNoZone(new Ipv6AddressNoZone(IPV6)))
+ .setRemote(new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1)))
+ .setEncapVrfId(ENCAP).setDecapVrfId(DECAP)
+ .setVni(new VxlanGpeVni(VNI))
+ .setNextProtocol(VxlanGpeNextProtocol.forValue(1))
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanValidatorTest.java
new file mode 100644
index 000000000..be8ae4694
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/VxlanValidatorTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.L2Input;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+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.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanValidatorTest {
+
+ private VxlanValidator validator;
+
+ @Mock
+ private WriteContext writeContext;
+ @Mock
+ private DisabledInterfacesManager interfaceDisableContext;
+
+ private static final String IPV6 = "a::100";
+ private static final String IPV4_1 = "192.168.20.10";
+ private static final String IPV4_2 = "192.168.20.11";
+ private static final Long VNI = Long.valueOf(11);
+ private static final Long ENCAP = Long.valueOf(123);
+ private static final String IFACE_NAME = "eth0";
+ private static final InstanceIdentifier<Vxlan> ID =
+ InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Vxlan.class);
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new VxlanValidator(ifcContext, interfaceDisableContext);
+ }
+
+ @Test
+ public void testWriteSuccessful() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanCorrect(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedMixedIpFamilies() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanMixedIpFamilies(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoSrc() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(false, true, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoDst() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, false, true, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoEncap() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, false, true), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedNoVNI() throws CreateValidationFailedException {
+ validator.validateWrite(ID, generateVxlanSetFields(true, true, true, false), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful() throws DeleteValidationFailedException {
+ validator.validateDelete(ID, generateVxlanCorrect(), writeContext);
+ }
+
+ private Vxlan generateVxlan(final IpAddressNoZone src, final IpAddressNoZone dst, final VniReference encapVrfId,
+ final long vni) {
+ final VxlanBuilder builder = new VxlanBuilder();
+ builder.setSrc(src);
+ builder.setDst(dst);
+ builder.setEncapVrfId(encapVrfId);
+ builder.setVni(new VxlanVni(vni));
+ builder.setDecapNext(L2Input.class);
+ return builder.build();
+ }
+
+ private Vxlan generateVxlanSetFields(final boolean src, final boolean dst, final boolean encapVrfId,
+ final boolean vni) {
+ final VxlanBuilder builder = new VxlanBuilder();
+ builder.setSrc(src
+ ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1))
+ : null);
+ builder.setDst(dst
+ ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2))
+ : null);
+ builder.setEncapVrfId(encapVrfId
+ ? new VniReference(ENCAP)
+ : null);
+ builder.setVni(vni
+ ? new VxlanVni(VNI)
+ : null);
+ builder.setDecapNext(L2Input.class);
+ return builder.build();
+ }
+
+ private Vxlan generateVxlanCorrect() {
+ return generateVxlanSetFields(true, true, true, true);
+ }
+
+ private Vxlan generateVxlanMixedIpFamilies() {
+ return generateVxlan(new IpAddressNoZone(new Ipv6AddressNoZone(IPV6)),
+ new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2)), new VniReference(ENCAP), VNI);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizerTest.java
new file mode 100644
index 000000000..1591b8e6a
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteCustomizerTest.java
@@ -0,0 +1,193 @@
+/*
+ * 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.hc2vpp.v3po.write.pbb;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.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 io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.jvpp.VppCallbackException;
+import io.fd.jvpp.core.dto.L2InterfacePbbTagRewrite;
+import io.fd.jvpp.core.dto.L2InterfacePbbTagRewriteReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.pbb.types.rev161214.Operation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
+
+ @Captor
+ private ArgumentCaptor<L2InterfacePbbTagRewrite> rewriteArgumentCaptor;
+
+ private NamingContext interfaceContext;
+ private PbbRewriteCustomizer customizer;
+ private InstanceIdentifier<PbbRewrite> validId;
+ private InstanceIdentifier<PbbRewrite> invalidId;
+
+ @Override
+ protected void setUpTest() throws Exception {
+ interfaceContext = new NamingContext("interface", "interface-context");
+ customizer = new PbbRewriteCustomizer(api, interfaceContext);
+
+ defineMapping(mappingContext, "pbb-interface", 1, "interface-context");
+ validId = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey("pbb-interface"))
+ .augmentation(PbbRewriteInterfaceAugmentation.class)
+ .child(PbbRewrite.class);
+
+ invalidId = InstanceIdentifier.create(PbbRewrite.class);
+ }
+
+ @Test
+ public void testWrite() throws WriteFailedException {
+ whenRewriteThenSuccess();
+ customizer.writeCurrentAttributes(validId, PbbRewriteValidatorTest.validData(), writeContext);
+ verifyRewriteRequest(desiredSetResult());
+ }
+
+ @Test
+ public void testWriteFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite validData = PbbRewriteValidatorTest.validData();
+ try {
+ customizer.writeCurrentAttributes(validId, validData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof WriteFailedException.CreateFailedException);
+ assertTrue(e.getCause() instanceof VppCallbackException);
+
+ final WriteFailedException.CreateFailedException ex = ((WriteFailedException.CreateFailedException) e);
+ assertEquals(validId, ex.getFailedId());
+ assertEquals(validData, ex.getData());
+ return;
+ }
+
+ fail("Test should have failed");
+ }
+
+ @Test
+ public void testUpdate() throws WriteFailedException {
+ whenRewriteThenSuccess();
+ final PbbRewrite rewrite = PbbRewriteValidatorTest.validData();
+ customizer.updateCurrentAttributes(validId, rewrite, rewrite, writeContext);
+ verifyRewriteRequest(desiredSetResult());
+ }
+
+ @Test
+ public void testUpdateFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite invalidData = PbbRewriteValidatorTest.invalidDataNoVlan();
+ final PbbRewrite validData = PbbRewriteValidatorTest.validData();
+ try {
+ customizer.updateCurrentAttributes(validId, invalidData, validData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof WriteFailedException.UpdateFailedException);
+ assertTrue(e.getCause() instanceof VppCallbackException);
+
+ final WriteFailedException.UpdateFailedException ex = ((WriteFailedException.UpdateFailedException) e);
+ assertEquals(validId, ex.getFailedId());
+ assertEquals(invalidData, ex.getDataBefore());
+ assertEquals(validData, ex.getDataAfter());
+ return;
+ }
+
+ fail("Test should have failed");
+ }
+
+ @Test
+ public void testDelete() throws WriteFailedException {
+ whenRewriteThenSuccess();
+ customizer.deleteCurrentAttributes(validId, PbbRewriteValidatorTest.validData(), writeContext);
+ verifyRewriteRequest(desiredDisableResult());
+ }
+
+ @Test
+ public void testDeleteFailedCallFailed() {
+ whenRewriteThenFail();
+ final PbbRewrite validData = PbbRewriteValidatorTest.validData();
+ try {
+ customizer.deleteCurrentAttributes(validId, validData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof WriteFailedException.DeleteFailedException);
+ assertTrue(e.getCause() instanceof VppCallbackException);
+ assertEquals(validId, ((WriteFailedException.DeleteFailedException) e).getFailedId());
+ return;
+ }
+
+ fail("Test should have failed");
+ }
+
+ private void whenRewriteThenSuccess() {
+ when(api.l2InterfacePbbTagRewrite(any())).thenReturn(future(new L2InterfacePbbTagRewriteReply()));
+ }
+
+ private void whenRewriteThenFail() {
+ when(api.l2InterfacePbbTagRewrite(any())).thenReturn(failedFuture());
+ }
+
+ private L2InterfacePbbTagRewrite desiredSetResult() {
+ final L2InterfacePbbTagRewrite desiredResult = new L2InterfacePbbTagRewrite();
+ desiredResult.swIfIndex = 1;
+ desiredResult.vtrOp = Operation.Pop2.getIntValue();
+ desiredResult.bDmac = new byte[]{-69, -69, -69, -69, -69, -69};
+ desiredResult.bSmac = new byte[]{-86, -86, -86, -86, -86, -86};
+ desiredResult.bVlanid = 1234;
+ desiredResult.iSid = 2;
+
+ return desiredResult;
+ }
+
+ private L2InterfacePbbTagRewrite desiredDisableResult() {
+ final L2InterfacePbbTagRewrite desiredResult = new L2InterfacePbbTagRewrite();
+ desiredResult.swIfIndex = 1;
+ desiredResult.vtrOp = 0;
+ desiredResult.bDmac = new byte[]{-69, -69, -69, -69, -69, -69};
+ desiredResult.bSmac = new byte[]{-86, -86, -86, -86, -86, -86};
+ desiredResult.bVlanid = 1234;
+ desiredResult.iSid = 2;
+
+ return desiredResult;
+ }
+
+ private void verifyRewriteRequest(final L2InterfacePbbTagRewrite desiredResult) {
+ verify(api, times(1)).l2InterfacePbbTagRewrite(rewriteArgumentCaptor.capture());
+
+ final L2InterfacePbbTagRewrite actualRequest = rewriteArgumentCaptor.getValue();
+
+ assertNotNull(actualRequest);
+ assertEquals(actualRequest.bVlanid, desiredResult.bVlanid);
+ assertEquals(actualRequest.iSid, desiredResult.iSid);
+ assertEquals(actualRequest.vtrOp, desiredResult.vtrOp);
+ assertEquals(actualRequest.outerTag, desiredResult.outerTag);
+ assertArrayEquals(actualRequest.bDmac, desiredResult.bDmac);
+ assertArrayEquals(actualRequest.bSmac, desiredResult.bSmac);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidatorTest.java
new file mode 100644
index 000000000..c559953ad
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/pbb/PbbRewriteValidatorTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write.pbb;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.pbb.types.rev161214.Operation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteValidatorTest {
+
+ private PbbRewriteValidator validator;
+ private InstanceIdentifier<PbbRewrite> validId;
+ private InstanceIdentifier<PbbRewrite> invalidId;
+
+ @Mock
+ private WriteContext writeContext;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new PbbRewriteValidator(ifcContext);
+ validId = InstanceIdentifier.create(Interfaces.class)
+ .child(Interface.class, new InterfaceKey("pbb-interface"))
+ .augmentation(PbbRewriteInterfaceAugmentation.class)
+ .child(PbbRewrite.class);
+
+ invalidId = InstanceIdentifier.create(PbbRewrite.class);
+ }
+
+ @Test
+ public void testWriteSuccessful()
+ throws CreateValidationFailedException {
+ validator.validateWrite(validId, validData(), writeContext);
+ }
+
+ @Test(expected = CreateValidationFailedException.class)
+ public void testWriteFailedInvalidIID()
+ throws CreateValidationFailedException {
+ validator.validateWrite(invalidId, validData(), writeContext);
+ }
+
+ @Test
+ public void testWriteFailedInvalidData() {
+ verifyInvalidWriteDataCombination(invalidDataNoDestination());
+ verifyInvalidWriteDataCombination(invalidDataNoSource());
+ verifyInvalidWriteDataCombination(invalidDataNoItag());
+ verifyInvalidWriteDataCombination(invalidDataNoOperation());
+ verifyInvalidWriteDataCombination(invalidDataNoVlan());
+ }
+
+ @Test
+ public void testUpdateFailedInvalidData() {
+ verifyInvalidUpdateDataCombination(invalidDataNoDestination());
+ verifyInvalidUpdateDataCombination(invalidDataNoSource());
+ verifyInvalidUpdateDataCombination(invalidDataNoItag());
+ verifyInvalidUpdateDataCombination(invalidDataNoOperation());
+ verifyInvalidUpdateDataCombination(invalidDataNoVlan());
+ }
+
+ @Test
+ public void testDeleteFailedInvalidData() {
+ verifyInvalidDeleteDataCombination(invalidDataNoDestination());
+ verifyInvalidDeleteDataCombination(invalidDataNoSource());
+ verifyInvalidDeleteDataCombination(invalidDataNoItag());
+ verifyInvalidDeleteDataCombination(invalidDataNoOperation());
+ verifyInvalidDeleteDataCombination(invalidDataNoVlan());
+ }
+
+ private void verifyInvalidWriteDataCombination(final PbbRewrite invalidData) {
+ try {
+ validator.validateWrite(validId, invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof CreateValidationFailedException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+ private void verifyInvalidUpdateDataCombination(final PbbRewrite invalidData) {
+ try {
+ validator.validateUpdate(validId, validData(), invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof UpdateValidationFailedException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+ private void verifyInvalidDeleteDataCombination(final PbbRewrite invalidData) {
+ try {
+ validator.validateDelete(validId, invalidData, writeContext);
+ } catch (Exception e) {
+ assertTrue(e instanceof DeleteValidationFailedException);
+ return;
+ }
+
+ fail("Verifying of invalid combination failed");
+ }
+
+ static PbbRewrite invalidDataNoDestination() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1234)
+ .setITagIsid(2L)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ static PbbRewrite invalidDataNoSource() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1234)
+ .setITagIsid(2L)
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ static PbbRewrite invalidDataNoItag() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1234)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ static PbbRewrite invalidDataNoVlan() {
+ return new PbbRewriteBuilder()
+ .setITagIsid(2L)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ static PbbRewrite invalidDataNoOperation() {
+ return new PbbRewriteBuilder()
+ .setITagIsid(2L)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+
+ static PbbRewrite validData() {
+ return new PbbRewriteBuilder()
+ .setBVlanTagVlanId(1234)
+ .setITagIsid(2L)
+ .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+ .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+ .setInterfaceOperation(Operation.Pop2)
+ .build();
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesCustomizerTest.java
new file mode 100644
index 000000000..879e8c08e
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesCustomizerTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.hc2vpp.v3po.write.span;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.jvpp.core.dto.SwInterfaceSpanEnableDisable;
+import io.fd.jvpp.core.dto.SwInterfaceSpanEnableDisableReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.SpanState;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Span;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MirroredInterfacesCustomizerTest extends WriterCustomizerTest {
+
+ private static final String IFACE_NAME = "iface";
+ private static final int IFACE_INDEX = 3;
+ private static final String SRC_IFACE_NAME = "src-iface";
+ private static final int SRC_IFACE_INDEX = 5;
+
+ private NamingContext interfaceContext;
+ private MirroredInterfaceCustomizer customizer;
+
+ private InstanceIdentifier<MirroredInterface> validId;
+ private MirroredInterface validData;
+
+ @Captor
+ private ArgumentCaptor<SwInterfaceSpanEnableDisable> requestCaptor;
+
+ @Override
+ public void setUpTest() {
+ interfaceContext = new NamingContext("iface", "iface-context");
+ customizer =
+ new MirroredInterfaceCustomizer(api, interfaceContext, id -> id.firstKeyOf(Interface.class).getName());
+ defineMapping(mappingContext, IFACE_NAME, IFACE_INDEX, "iface-context");
+ defineMapping(mappingContext, SRC_IFACE_NAME, SRC_IFACE_INDEX, "iface-context");
+
+ validId = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Span.class)
+ .child(MirroredInterfaces.class)
+ .child(MirroredInterface.class);
+
+ validData = new MirroredInterfaceBuilder()
+ .setIfaceRef(SRC_IFACE_NAME)
+ .setState(SpanState.Receive)
+ .build();
+
+ when(api.swInterfaceSpanEnableDisable(any())).thenReturn(future(new SwInterfaceSpanEnableDisableReply()));
+ }
+
+ @Test
+ public void writeCurrentAttributes() throws Exception {
+ customizer.writeCurrentAttributes(validId, validData, writeContext);
+ verify(api, times(1)).swInterfaceSpanEnableDisable(requestCaptor.capture());
+ assertCreateRequest(requestCaptor.getValue());
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void updateCurrentAttributes() throws Exception {
+ customizer.updateCurrentAttributes(validId, validData, validData, writeContext);
+ }
+
+ @Test
+ public void deleteCurrentAttributes() throws Exception {
+ customizer.deleteCurrentAttributes(validId, validData, writeContext);
+ verify(api, times(1)).swInterfaceSpanEnableDisable(requestCaptor.capture());
+ assertDeleteRequest(requestCaptor.getValue());
+ }
+
+ private static void assertCreateRequest(final SwInterfaceSpanEnableDisable createRequest) {
+ assertNotNull(createRequest);
+ assertEquals(1, createRequest.state);
+ assertEquals(IFACE_INDEX, createRequest.swIfIndexTo);
+ assertEquals(SRC_IFACE_INDEX, createRequest.swIfIndexFrom);
+ }
+
+ private static void assertDeleteRequest(final SwInterfaceSpanEnableDisable deleteRequest) {
+ assertNotNull(deleteRequest);
+ assertEquals(0, deleteRequest.state);
+ assertEquals(IFACE_INDEX, deleteRequest.swIfIndexTo);
+ assertEquals(SRC_IFACE_INDEX, deleteRequest.swIfIndexFrom);
+ }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesValidatorTest.java
new file mode 100644
index 000000000..4bf1230f5
--- /dev/null
+++ b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/write/span/MirroredInterfacesValidatorTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2019 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.hc2vpp.v3po.write.span;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.SpanState;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Span;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MirroredInterfacesValidatorTest {
+
+ private InstanceIdentifier<MirroredInterface> validId;
+ private MirroredInterfaceValidator validator;
+ private static final String IFACE_NAME = "iface";
+ private static final String SRC_IFACE_NAME = "src-iface";
+
+ @Mock
+ private WriteContext writeContext;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+ validator = new MirroredInterfaceValidator(ifcContext, id -> id.firstKeyOf(Interface.class).getName());
+ validId = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+ .augmentation(VppInterfaceAugmentation.class).child(Span.class)
+ .child(MirroredInterfaces.class)
+ .child(MirroredInterface.class);
+ }
+
+ @Test
+ public void testWriteSuccessful()
+ throws DataValidationFailedException.CreateValidationFailedException {
+ validator.validateWrite(validId, validData(), writeContext);
+ }
+
+ @Test
+ public void testWriteFailed() {
+ validateWritingIncorrectData(incorrectDataNoIfaceRef());
+ validateWritingIncorrectData(incorrectDataNoSpanState());
+ }
+
+ @Test
+ public void testUpdateSuccessful()
+ throws DataValidationFailedException.UpdateValidationFailedException {
+ validator.validateUpdate(validId, validData(), validData(), writeContext);
+ }
+
+ @Test
+ public void testDeleteSuccessful()
+ throws DataValidationFailedException.DeleteValidationFailedException {
+ validator.validateDelete(validId, validData(), writeContext);
+ }
+
+ private void validateWritingIncorrectData(final MirroredInterface data) {
+ try {
+ validator.validateWrite(validId, data, writeContext);
+ } catch (DataValidationFailedException.CreateValidationFailedException e) {
+ assertTrue(e instanceof DataValidationFailedException.CreateValidationFailedException);
+ return;
+ }
+ fail("Verifying of invalid combination failed");
+ }
+
+ private MirroredInterface incorrectDataNoIfaceRef() {
+ return new MirroredInterfaceBuilder()
+ .setIfaceRef(null)
+ .setState(SpanState.Receive)
+ .build();
+ }
+
+ private MirroredInterface incorrectDataNoSpanState() {
+ return new MirroredInterfaceBuilder()
+ .setIfaceRef(SRC_IFACE_NAME)
+ .setState(null)
+ .build();
+ }
+
+ private MirroredInterface validData() {
+ return new MirroredInterfaceBuilder()
+ .setIfaceRef(SRC_IFACE_NAME)
+ .setState(SpanState.Receive)
+ .build();
+ }
+}